The router Directive to indicate the place where the Angular router will load the Component of the currently selected route.
routerLink
Do not used the <a href="" /> to load routes, because these routes will be loaded but the page will also be reloaded, thus states will be lost.
<!-- Full Path -->
<a routerLink="/employee"></a>
<!-- Relative Path -->
<a routerLink="employee"></a>
<!-- Can be used with Arrays to declare multiple hierarchical paths like '/employee/new' -->
<a [routerLink]="['/employee']"></a>
<a [routerLink]="['/employee', 'new']"></a>
It can be used with Absolute paths or Relative paths.
Absolute paths always starts with / like /home.
Relative paths starts without the/, and always append the passed url to the current url.
You can use ../, like in directories, to remove go back to upper Url paths.
export class HomeComponent {
// Access the dynamic data with Signals
message = input.required<string>();
...
}
// Can use the snapshot since it is executed every time the Route is active
export const resolveMessage: ResolveFn<string> = (activatedRoute: ActivatedRouteSnapshot, routerState: RouterStateSnapshot) => {
// You may `inject` services in here
// ...
return 'Hello: ' + data; // data is of type string
}
dynamic data - with Resolve Classes as Services (Avoid)
This is an older way, prefer the use with Functions. (Above)
You can pass dynamic data to routes with services implementing Resolve class.
@Injectable({
providedIn: "root",
})
export class MessageResolver implements Resolve<string> {
resolve(activatedRoute: ActivatedRouteSnapshot, routerState: RouterStateSnapshot) {
return "Hello: " + data; // data is of type string
}
}
You can retrieve url parameters by having a variable with the exact same name as declared in the Route.
The expected type will always be stringsince the url is a string.
@Component({ ... })
export class UserComponent {
// user/:userId
// You may use `required` since Url param will most likely be required in the URL
userId = input.required<string>();
}
Retrieving multiple params /:userId/:name
@Component({ ... })
export class UserComponent {
// user/:userId
userId = input.required<string>();
name = input.required<string>();
}
Retriving Url queryParams ?allowEdit=value
Just like a /:param, for queryParams just create a variable with the same name as the queryParam.
@Component({ ... })
export class UserComponent {
// user?order=value
// For queryParams don't use `required` since usually are opcional values
order = input<'asc' | 'desc'>();
}
Retrieving Url fragments #loading
Not sure how to retrieve with Signals, but it could be just setting the variable input() with the same name as the #fragment name.
Fetching Url data - with ActivatedRoute service
With Observables a Component can by default access it's own route params AND parent route params.
Changes in the URL will use still use the same Component's instance.
This means that ngOnInit will NOT execute again, and changes in :params for instance will not be picked.
Retrieving data with Observables will garantee to get the new values.
Retriving data with snapshot will NOT get new values.
Fetching data the Reactive way - with (Observable)
Retrieving Url params /:userId - with paramMap
You can access url params by subscribing to paramMap property of ActivatedRoute.
It is code that can be executed before a route is loaded or when leaving a route, that checks whether a certain navigation action should be permitted or not.
Typically guards will have their own files <guard-name>.guard.ts.
Useful for preventing unauthorized access.
Add Guards to routes by using the routes properties that start with can.
By default a Guard will guard the Route where it was declared, and it's child routes.
Guards can be defined by:
Guard functions.
Guard Services that implement certain interfaces (This is the old way)
const appRoutes: Routes = [
{
path: "",
component: HomeComponent,
// They receive an array of Guards (Functions or Classes)
canMatch: [],
canActivate: [],
canActivateChild: [],
canDeactivate: [],
},
];
canMatch
Allows you to control whether the entire route should be matched by a certain navigation action or not.
For instance, if some path that has been entered into the Url should match this route or not.
with Functions
/**
* route: Current route that is trying to be matched.
* segments: An array of Url path segments.
*/
export const authGuard: CanMatchFn = (route: Route, segments: UrlSegment[]) => {
// Return `true` to grant access to the route, `false` to deny it
return true;
// Or you may return a UrlTree to redirect the navigation
return router.parseUrl("/home");
// Or you can redirect like this
return new RedirectCommand(router.parseUrl("/home"));
};
Comes one step after canMatch but before the component has been loaded.
It will be checked by Angular once a route has been identified as matching for the currently active path.
export const authGuard: CanActivateFn = (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => {
// Return `true` to grant access to the route, `false` to deny it
return true;
// Or you may return a UrlTree to redirect the navigation
return router.parseUrl("/home");
// Or you can redirect like this
return new RedirectCommand(router.parseUrl("/home"));
};
canActivateChild
Can be used if you want to activate the route, the Component, but not necessarily the child components of that route.
export const authGuard: CanActivateChildFn = (childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot) => {
// Return `true` to grant access to the route, `false` to deny it
return true;
// Or you may return a UrlTree to redirect the navigation
return router.parseUrl("/home");
// Or you can redirect like this
return new RedirectCommand(router.parseUrl("/home"));
};
canDeactivate
To control whether a user is allowed to leave a page or not.
export class HomeComponent {
unsavedData = signal<boolean>(false);
}
// Specify `HomeComponent` as the implicit type of `CanDeactivateFn` so that you receive it in the `component` parameter
export const canLeavePage: CanDeactivateFn<HomeComponent> = (component: T, currentRoute: ActivatedRouteSnapshot, currentState: RouterStateSnapshot, nextState: RouterStateSnapshot) => {
// Return `true` to let navigate out of the component, or `false` to deny it
if (component.unsavedData() === false) return false;
return true;
// Making a confirmation dialog
if (component.unsavedData() === false) {
return window.confirm("Do you really want to leave?");
}
return true;
// You may also return a UrlTree to redirect the navigation
return router.parseUrl("/home");
};