DEV Community

Cover image for Angular Dart Router - Navigation
Hadrien Lejard
Hadrien Lejard

Posted on

Angular Dart Router - Navigation

Navigation is probably the most important feature of a Router, we will have a look are our options to navigate from a Component route to another and pass data to your component through the URL.

First, let's consider the followings RoutePath definitions.

import 'package:angular/angular.dart';
import 'package:angular_router/angular_router.dart';

class AppRoutes {
  static final list = RoutePath(path: 'list');
}

final routes = <RouteDefinition>[
    RouteDefinition(
      routePath: AppRoutes.list, 
      component: ng.ListComponentNgFactory,
    ),
];
Enter fullscreen mode Exit fullscreen mode

Basic navigation

You can simply use the navigate method from the Router and defined RoutePath to build the URL you want to navigate to.

@Component(
  selector: 'nav-bar',
  template: '''
  <div (click)="navigateToList()">List</div>
  ''',
)
class NavBarComponent {
  final Router router;
  NavBarComponent(this.router);

  void navigateToList() {
    router.navigate(AppRoutes.list.toUrl());
  }
}
Enter fullscreen mode Exit fullscreen mode

It works but, you are not really following HTML semantics. To navigate between pages you should be using an Anchor element and set href attribute on it.

However, if you try to set it manually as follow.

<a [attr.href]="AppRoutes.list.toUrl()">List</a>
Enter fullscreen mode Exit fullscreen mode

It won't always work since the element is not aware of your LocationStrategy and your <base href="..."> configuration.

To set the URL on an anchor, angular provides the RouterLink directive that you can use as a replacement of the href attribute.

<a [routerLink]="AppRoutes.list.toUrl()">List</a>
Enter fullscreen mode Exit fullscreen mode

As a bonus, you will be able to use the RouterLinkActive directive to apply CSS class to your element if the URL is currently active.

<a [routerLink]="AppRoutes.list.toUrl()"
   routerLinkActive="my-class">
  List
</a>
Enter fullscreen mode Exit fullscreen mode

Navigate with parameters

2 types of parameters are available.

The first one, simply calls parameters could be considered as required parameters, that must be predefined in the RoutePath definition.

class AppRoutes {
  ...
  /// required parameter with name 'idemId'
  static final listItem = RoutePath(path: 'list/:itemId');
}

final routes = <RouteDefinition>[
    ...
    RouteDefinition(
      routePath: AppRoutes.listItem, 
      component: ng.ListItemComponentNgFactory,
    ),
];
Enter fullscreen mode Exit fullscreen mode

The second one, queryParameters are mostly optional parameters, in the URL, this is everything that comes after ? and separated by &. (ex: example.com?foo=bar&val=42)

Now, imagine you want to navigate to a specific list item and you also want to pass an optional value to the ListItemComponent to make a feature visible or not for example. You just need to use available parameters of the RoutePath.toUrl method.

/// can be use with RouterLink directive
String buildListItemUrl(String id) {
  return AppRoutes.listItem.toUrl(
    parameters: { 'itemId': id },
    queryParameters: { 'showAwesomeFeature': 'true' },
  );
}

// or
void navigateToListItem(String id) {
  router.navigate(buildListItemUrl(id));
}
Enter fullscreen mode Exit fullscreen mode

Both parameters must be strict Map<String, String> objects. if you want to pass complex data, you must have a way to encode/decode it.

Read URL parameters

Now that you know how to build URLs and trigger navigation to the route component. You probably want to access the info you stored in the URL.

To do so, you need to implement the OnActivate provided by Angular on your component.

import 'package:angular/angular.dart';
import 'package:angular_router/angular_router.dart';

@Component(
  ...
)
class ListItemComponent implements OnActivate {
  @override
  void onActivate(RouterState previous, RouterState current) { ... }
}
Enter fullscreen mode Exit fullscreen mode

Each time the router navigates to this component, the onActivate method is called and gives you access to the previous and the current RouterState containing both parameters that you can decode.

void onActivate(RouterState previous, RouterState current) {
  final listItemId = current.parameters['itemId'];
  fetchItem(listItemId);

  showAwesomeFeature = current.queryParameters['showAwesomeFeature'] == 'true';
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)