This is my code,
import 'package:angular/angular.dart';
class AppModule extends Module {
AppModule(){
type(AppController);
type(LoginController);
type(RouteInitializer, implementedBy: AppRouter);
}
}
class AppRouter implements RouteInitializer {
init(Router router, ViewFactory view) {
router.root
..addRoute(
name: 'login',
path: '/login',
enter: view('app/views/login.tpl.html'))
..addRoute(
defaultRoute: true,
name: 'index',
enter: view('app/views/index.tpl.html'));
}
}
#NgController(selector: '[app-ctrl]', publishAs: 'ctrl')
class AppController {
}
#NgController(selector: '[login-ctrl]', publishAs: 'ctrl')
class LoginController {
Http _http;
String works = 'Works.';
LoginController(this._http);
}
No routes are working, clicking on a '#/login' link does not change the url or the view.
Log says
clicked /app/web/index.html#/login
route /app/web/index.html [Route: null]
route [Route: index]
What am I doing wrong?
There might be a couple of problems with this code. From what I can see the most likely problem is that the routing is using pushState. When you use pushState you don't manipulate the url using a hash. For more information on that see:
Manipulating Browser History
Angular will use push state when a browser supports it.
bind(NgRoutingUsePushState, toValue: new NgRoutingUsePushState.value(false));
Giving you are module of:
class AppModule extends Module {
AppModule(){
bind(AppController);
bind(LoginController);
bind(RouteInitializer, implementedBy: AppRouter);
bind(NgRoutingUsePushState, toValue: new NgRoutingUsePushState.value(false));
}
}
Other possible problems include:
Not having an ng-view directive
Not setting the ng-bind-route in app/views/login.tpl.html, and app/views/index.tpl.html
When I made all these changes your code worked correctly for me when navigating to #/login
Related
I'm going to be crazy with routing, since angular2 RC1 i cannot route correctly, the last error i have is :
EXCEPTION: Error: Uncaught (in promise): Component 'LoginForm' does
not have route configuration
My code is bellow (i hoppe the usefull parts)
I cannot understand the message of error, what i want is just some links available on my main page using the '[routerLink]' routing to the correct components (my main activities)
Regards
Note : "/app/" is just a base path for my app urls (it does not correspond to a component)
bootstrap(AppComponent,[
ROUTER_PROVIDERS
]);
/////////////////////
#Component({
selector: 'my-app',
template: `
<navbartop></navbartop>
<h1>MAIN APP COMP</h1>
<a [routerLink]="['/app/coursesactivity']">CouresesActivity</a>
<router-outlet></router-outlet>
`,
directives: [ROUTER_DIRECTIVES, NavBarTop],
providers: [ROUTER_PROVIDERS]
})
#Routes([
{ path: '/app/login', component: LoginForm },
{ path: '/app', component: LoginForm }
])
export class AppComponent implements OnInit, OnActivate {
.....
}
/////////////////////
#Component({
selector: 'loginform',
templateUrl: '/app/components/compLoginForm/LoginForm.component.html',
styles: ['/app/components/compLoginForm/LoginForm.component.css']
})
export class LoginForm implements OnInit {//, OnActivate {
constructor(
//private _router: Router
//private _routeData: RouteData, deprecated
//private _routeParams: RouteParams deprecated
) {
}
...
}
I decided to cleanup the code, i encountered other errors,
finally i don't know where the original error came from...
Sorry for thos who helped me.
Regards
After all the deprecation in AngularDart , now configuring routes via the below initRoutes method inside my modules constructor.
//inside the main of the appliction
..
this.bind(RouteInitializerFn, toValue:initRoutes);
this.bind(NgRoutingUsePushState, toFactory:(_) => new NgRoutingUsePushState.value(false));
//in routeconfig.dart file which is imported in the main.dart
void initRoutes(Router router, RouteViewFactory viewFactory) {
viewFactory.configure({
'loginPage': ngRoute(
path: '/loginPage',
view: 'view/loginPage.html'),
'landingPage': ngRoute(
path: '/landingPage',
view: 'view/landingPage.html',
defaultRoute: true,
enter: _checkAuthentication
...
My question is how to inject the Service class which has the _checkAuthentication method in routeconfig.dart ? Since it's not a class how can get the dependency injection here ? or is there another way to initialize and register the RouteInitializerFn in the Module contructor ?
You can use the following technique: functions can be implemented as classes with the 'call' method.
#Injectable()
class MyRouteInitializer implements Function {
AuthService service;
MyRouteInitializer(this.service);
call(Router router, RouteViewFactory viewFactory) {
...
service._checkAuthentication();
...
}
}
Function registration in the module:
this.bind(RouteInitializerFn, toImplementation: MyRouteInitializer);
I'm switching my app over to the new routing DSL. Specifically, I want to do something like this with preEnter:
final RouteInitializerFn routes =(Router router, ViewFactory views) {
views.configure({
'chat': ngRoute(
path: '/chat',
// authService.requireState returns a Future<bool>, and may invoke an HttpRequest
preEnter: (RoutePreEnterEvent e) => e.allowEnter(authService.requireState(LOGGED_IN)),
view: 'views/chat.html'),
'login': ngRoute(
path: '',
defaultRoute: true,
view: 'views/login.html')
});
}
This would be configured in the module as follows:
value(RouteInitializerFn, routes);
In case you missed it, I'm referencing an injectable authService within the RouteInitializerFn. This isn't possible since RouteInitializerFn is a function and not a class, so nothing can be injected into it. If I encapsulated the routes function within a class, I'm not sure how I could configure RouteInitializerFn, so I'm in a bit of a quandary.
I found a pretty cool solution to this problem. Turns out, if you define a call method on a class that satisfies a typedef, you can configure it as an implementation of the typedef. Very cool. Here is my solution:
class Routes
{
final UserService _userService;
Routes(this._userService);
void call(Router router, ViewFactory views)
{
views.configure({
'chat': ngRoute(
path: '/chat',
preEnter: (RoutePreEnterEvent e) => e.allowEnter(this._userService.requireUserState(UserService.LOGGED_IN)),
view: 'views/chat.html'
),
'login': ngRoute(
path: '',
defaultRoute: true,
view: 'views/login.html'
)
});
}
}
and this is how it's configured within the module:
// old syntax
type(RouteInitializerFn, implementedBy: Routes);
// new syntax
bind(RouteInitializerFn, toImplementation: Routes);
I have a basic Angular Dart program which currently allows logging in and shows a basic dashboard when logged in. What I would like to do is redirect to the dashboard route after a successful login. I do not know how to access the router object from within the login controller, attempts to use DI to load in Router to the controller work but give me a fresh Router object instead of the previously initialised one (as expected).
main.dart
import 'package:angular/angular.dart';
import 'dart:convert' show JSON;
import 'dart:html';
class TTRouter implements RouteInitializer {
Cookies _cookies;
TTRouter(this._cookies);
init(Router router, ViewFactory view) {
router.root
..addRoute(
name: 'login',
path: '/login',
enter: view('login.partial.html'))
..addRoute(
name: 'home',
path: '/dashboard',
enter: view('dashboard.partial.html'));
}
}
#NgController(
selector: '[login-controller]',
publishAs: 'ctrl')
class LoginController {
Http _http;
Scope _scope;
LoginController(this._scope, this._http);
login() {
// Login API request ommitted
// TODO: insert redirect to 'home' route here
}
}
class TTModule extends Module {
TTModule() {
type(RouteInitializer, implementedBy: TTRouter);
type(LoginController);
factory(NgRoutingUsePushState,
(_) => new NgRoutingUsePushState.value(false));
}
}
main() => ngBootstrap(module: new TTModule());
login() is called using ng-submit="ctrl.login() from the login partial view.
I would be grateful for any comments on the structure of the code as well if I'm approaching this the wrong way. I am new to both Dart and Angular (read/watched tutorials but this is the first app I am building on my own).
If you add the router as value to the module instead of type you get the same instance every time.
TTModule() {
value(RouteInitializer, new TTRouter());
}
try with NgRoutingHelper.
class LoginController {
Http _http;
Scope _scope;
NgRoutingHelper locationService;
LoginController(this._scope, this._http, NgRoutingHelper this.locationService );
login() {
// Login API request ommitted
// TODO: insert redirect to 'home' route here
locationService.router.go('home', {} );
}
}
don't forget to add the service in your module
type(NgRoutingHelper );
You should be always getting the same instance of the Router -- there can only be one, otherwise unpredictable things will start happening.
class LoginController {
Http _http;
Scope _scope;
Router _router;
LoginController(this._scope, this._http, this._router);
login() {
_router.go('home', {} );
}
}
I'm using AngularDart and routing. My views are one-liners that contain a single component. I feel the views are not carrying their weight. Can I route directly to a component?
Example:
router.root
..addRoute(
name: 'welcome',
path: '/welcome',
defaultRoute: true,
enter: view('views/welcome.html'))
..addRoute(
name: 'camera',
path: '/camera',
enter: view('views/camera.html'));
And here's views/welcome.html
<welcome></welcome>
And here's views/camera.html
<camera></camera>
As you can see, those views are pretty weak. I'm much rather say: "when you enter a view, insert this component"
Is that possible?
This seems to be directly supported now
see https://github.com/angular/angular.dart/issues/425
You can route to an inline template (viewHtml):
views.configure({
'foo': ngRoute(
path: '/foo',
viewHtml: '<foo-component></foo-component>')
});
I wanted to ask the same question, but you were the first! I found a solution, probably not the best one, but at least it works.
I created one html for all routes:
dyn_view.html:
<div><dynamic-view></dynamic-view></div>
and of course a component dynamic-view, which takes actual component tag name from the route provider and dynamically adds to the DOM using the technique described here: How to add a component programatically in Angular.Dart?
dynamic_view.html
<div></div>
dynamic_view.dart
#NgComponent(
selector: 'dynamic-view',
templateUrl: 'view/dynamic_view.html'
)
class DynamicView implements NgShadowRootAware {
Compiler compiler;
Injector injector;
String elementName;
DynamicView(this.compiler, this.injector, RouteProvider provider) {
elementName = provider.parameters["elementName"];
}
void onShadowRoot(ShadowRoot shadowRoot) {
DivElement inner = shadowRoot.querySelector("div");
inner.appendHtml("<$elementName></$elementName>");
BlockFactory template = compiler(inner.nodes);
var block = template(injector);
inner.replaceWith(block.elements[0]);
}
}
Now the router. The element name must be passed somehow to the RouteProvider. I was inspired by this post: Verifying route preconditions prior to loading controller
class DynamicViewFactory {
ViewFactory viewFactory;
DynamicViewFactory(this.viewFactory);
call(String elementName) {
return (RouteEvent event) {
event.parameters["elementName"] = elementName;
viewFactory("view/dyn_view.html")(event);
};
}
}
class MyRouteInitializer implements RouteInitializer {
init(Router router, ViewFactory view) {
DynamicViewFactory dynView = new DynamicViewFactory(view);
router.root
..addRoute(
name: 'route1',
path: '/a/:b',
enter: dynView('componentA'))
..addRoute(
name: 'route2',
path: '/b/:c',
enter: dynView('componentB'));
}
}
The above code is slightly modified from what actually I use, so it can have some small bugs, but the general idea is the same.
Hope that helps!