• 18. Juni 2016

Influencing Routing with Guards using the new Angular-2-Router

Update in January 2017: This post has been updated to use the final API of Angular 2.x.

The German version of this article can be found here.

Using Guards, Angular-Applications can get informed about changes to the current route by the new Angular-2-Router that is available since June 2016. These Guards are just services. Their methods that are defined by interfaces are called by the router when it activates or deactivates a component. The returned value defines whether the router is allowed to perform the requested route-change. Valid values are true, false and Observable<boolean>. The latter one allows to postpone the decision so that the application can delegate to a service or talk to the user before making up its decision.

For implementing guards, the router provides two interfaces: CanActivate defines the method canActivate that is executed by the router before activating a component. The interface CanDeactivate in turn comes with a method canDeactivate that is executed before deactivating a component. This article shows how an application can use canDeactivate to ask the user for permission before leaving a component. The sourcecode for this sample can be found here.

sample

Implementing a Guards

The here presented guard is a simple Angular-2-Service that implements the interface CanDeactivate. This interface has to be parametrised with the type of the component it is indented for:

import { CanDeactivate, ActivatedRouteSnapshot, RouterStateSnapshot} from '@angular/router';
import { FlightEditComponent} from './flight-edit.component';

export class FlightEditGuard implements CanDeactivate<FlightEditComponent> {

    canDeactivate(
            component: FlightEditComponent, 
            route: ActivatedRouteSnapshot, 
            state: RouterStateSnapshot) {

                return component.canDeactivate();
    }

}

Implementing the component

The method canDeactivate takes the instance of the component in question as well as parameters that inform about the current and the requested future state of the router. The here described implementation delegates to the component so that it can display a warning for the user.

The method canDeactivate within the component which is called by the guard sets the property exitWarning.show to true to show the warning. This warning asks the user whether they really want to leave the route. As canDeactivate has to wait for their decision it returns an Observable<boolean> and stores the equivalent Observer<boolean> into exitWarning.observer.

The method decide takes the decision from the user and hides the warning by setting exitWarning.show back to false. After that, it sends the received decision to the router by using the Overserver.

import { Component} from '@angular/core';
import { ActivatedRoute} from '@angular/router';
import { Observable, Observer} from 'rxjs';

@Component({
    template: require('./flight-edit.component.html')
})
export class FlightEditComponent {

	[...]    

    exitWarning = {
        observer: null,
        show: false
    }

    decide(d: boolean) {
        this.exitWarning.show = false;
        this.exitWarning.observer.next(d);
        this.exitWarning.observer.complete();
    }

    canDeactivate() {
        this.exitWarning.show = true;
        return new Observable<boolean>((sender: Observer<boolean>) => {
            this.exitWarning.observer = sender;
            
        });
    }

}

The template for the warning can be found in the next listing. It shows the warning in lieu of exitWarning.show. The descion of the user is delegated to the method decide.

<div *ngIf="exitWarning.show" class="alert alert-warning">
        <div>
        Daten wurden nicht gespeichert! Trotzdem Maske verlassen?
        </div>
        <div>
            <a href="javascript:void(0)" (click)="decide(true)" class="btn btn-danger">Ja</a>
            <a href="javascript:void(0)" (click)="decide(false)" class="btn btn-default">Nein</a>
        </div>
</div>

Registering guard within the router-configuration

To register the guard for a component, its entry within the router-configuration has to point to it via the array canDeactivate:

const APP_ROUTES: RouterConfig = [
    {
        path: '/home',
        component: HomeComponent,
        index: true
    },
    {
        path: '/flight-booking',
        component: FlightBookingComponent,
        children: [
            {
                path: '/flight-search',
                component: FlightSearchComponent
            },
            {
                path: '/passenger-search',
                component: PassengerSearchComponent
            },
            {
                path: '/flight-edit/:id',
                component: FlightEditComponent,
                canDeactivate: [FlightEditGuard]
            }
        ]
    }
];

Strictly speaking, canDeactivate only points to a token which has to be bound to a service with a provider. The following listing creates a such a provider using the usual abbreviated form:

import { OAuthModule } from 'angular-oauth2-oidc';

[...]

@NgModule({
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule,
    [...]
  ],
  providers: [
    FlightEditGuard
  ]
  [...]
})
export class AppModule {
}

 

 
Hier können Sie eine Anfrage für eine unverbindliche Schulung ode Beratung bzw. einen Workshop erstellen.
 
Unverbindliche Anfrage
 
 

Schulungen

Angular Schulung: Strukturierte Einführung

Lernen Sie in dieser interaktiven Schulung anhand einer Beispielanwendung den Einsatz von Angular für Ihre erfolgreichen Projekte kennen. Sie durchdringen die Hintergründe und bauen von der ersten Minute an auf Best Practices auf.

Details

Advanced Angular: Enterprise-Anwendungen und Architektur

In dieser Schulung erfahren Sie alles für die Entwicklung großer Anwendungen mit Angular: Mono-Repos, Micro-Apps, State Management, Performance und mehr

Details

Angular: Strukturierte Einführung

Seit der Ankündigung von Angular (2+) fragen sich Entwicklungs-Teams, welche Migrationspfade für AngularJS-1.x-Anwendungen vorliegen werden. Das im Lieferumfang von Angular enthaltene ngUpgrade bietet eine Antwort darauf. Es erlaubt einen Parallelbetrieb von AngularJS 1.x und Angular (2+) und stellt somit die Grundlage für eine schrittweise Migration dar.

Details

Progressive Web-Apps mit Angular

Progressive Web Apps bieten den Komfort nativer Anwendungen, indem sie auf moderne Browser APIs, wie Service Worker, setzen. Sie sind installierbar sowie offlinefähig und nutzen Hintergrundprozesse für Datensynchronisation und Push-Notifications. Diese Schulung zeigt anhand eines durchgehenden Beispiels was sich genau hinter diesem neuen Konzept verbirgt, wie solche Anwendungen mit Angular entwickelt werden und wie Sie in Ihren Projekten von den dahinterstehenden Ideen profitieren.

Details

Reaktive Architekturen mit Angular und Redux

Dieses interaktive Seminar vermittelt, wie Sie reaktive Anwendungen mit Angular entwickeln können.

Details

TypeScript

TypeScript gibt Ihnen alle Möglichkeiten der neuen JavaScript-Standards und zusätzlich ein statisches Typsystem, das dabei hilft, Fehler möglichst früh zu erkennen. Außerdem ist TypeScript die Grundlage für Angular. In diesem interaktiven Seminar lernen Sie diese mächtige Sprache anhand einer Fallstudie kennen.

Details

Weitere Schulungen ...