A great way to take your app to the next level is to implement
Guards, which are interfaces that protect routes and grant access based on defined permissions. This is useful for apps with an admin dashboard.
Think of a
WordPress where a user can access the dashboard once logged in.
Check out the final application below!
What Guards Are
Why Use Guards
How To Create A Guard
How To Integrate A Guard To A Route
CLI make a new app, in this example
<app-name> will be
Once our new app is generated run the app:
Now that we know our app is working we can begin to build our components.
We need two components:
Dashboard- Our component we'll protect from users with no permission.
Login- Our component that will grant user permission to access the dashboard component.
Generate the two components:
CLI will automatically add our components to the
Let's create a routing module to handle what components a user will see when browsing our app.
Create a module named
--flat option will only generate a file instead of a folder. and it will be on the base level.
--module option is to tell the cli which module to register the new module to. in this example it is the 'app' module.
The generated file
app-routing.module.ts will look like this:
app-routing.module.ts file import the
Dashboard components. Also import the
Now that we have our components imported next create an array of objects named routes of type
Routes. Each object is a route with a path and a component to render to that path.
keep in mind the order of the paths matters as the first one matched will be rendered.
Our path value is which url path the component will render to. An empty path
'' is used alongside the property
redirectTo with a value of
/login and the property
pathMatch with the value full to tell the browser to re-direct the user to the login path if the url path is empty.
We want our router to be configured at the app's root level. To do so we'll use the
forRoot() method from
RouterModule to the
@NgModule() metadata imports array and pass the routes array into
RouterModule so that the
AppModule can utilize the
router-outlet directive and other directives including service providers anywhere in the app.
app-routing.module.ts file will look like this completed.
CommonModule and declarations are removed since they are unused. It's good practice to remove what you don't use. This keeps code bloat to a minimum.
Make sure the
AppModule has the
AppRoutingModule imported. The file should look like this.
If we visit the browser and navigate to our paths notice that nothing changes. Why is that?
We've missed one crucial step, which is implementing the
Let's open the
app.component.html file, replace all its content with the
router-outlet and simple navigation to our login and dashboard routes.
The app's template should look like this:
we are able to use
routerLink thanks to the
Once that's done we can visit each of our paths directly in the browser.
The next thing to do is to update the
We can now see our components render to the browser. Let's stub out functionality. Stubbing is like blueprinting. We add placeholder functionality as a guide which helps in debugging.
What we want is for the
Login component to handle access to our dashboard by granting the user permission via a guard (more on this later).
What we've done is to interpolate a simple message that is attached to the two buttons click events that call our methods:
We'll revisit the
Login component later to integrate the guard we're creating next.
Guards are interfaces that return a
Promise< boolean >,
Observable< boolean >, a
boolean, or a
There are multiple types of guards:
CanActivate-Controls access to a route.
CanActivateChild- Controls access to a child route.
CanDeactivate- Mediate navigation away from the current route.
Resolve- Perform route data retrieval before route activation.
CanLoad- Mediate navigation to a feature module loaded async.
Create a new
auth inside a new folder,
By default our newly generated guard implements the
CanActivate guard interface.
auth.guard.ts contains a method
canActivate() that accepts the parameters: next, and state and returns a boolean.
Go to the
app-routing.module.ts file and import the newly created
guard to our
Tie the imported
guard to the
route we want protected which is the
Next we need to update our guard with specific conditions. These conditions we'll create through a service.
we are making a service to mock authentication conditions. our guard will call the service to login a user and retain that user's information.
generate a service named
auth inside a folder named
We now have a bare-bones service file.
Update the service:
We have created a login method as an observable, a logout method, a boolean flag
isLoggedIn and a string variable
Import the operators
Update the login method to return an emitted value of true. This will simulate an
Add a pipe method and use
tap after a 1sec delay to toggle the
isLoggedIn flag to true.
In the logout method toggle the
isLoggedIn flag to false.
auth.service.ts should now look like this:
Our service is now ready to perform a login authentication. Let's implement it in our guard.
Now that we have a service we can use its functionality in our guard.
Import our newly created
AuthService and inject it in the constructor along with
auth.guard.ts file to this:
The changes made are:
A new method
checkLogin()which accepts a url string. The method returns true if the
isLoggedInflag from the
AuthServiceis true, sets the
AuthServiceto the passed in url then navigates to the login path and returns false.
canActivate()method now returns a call to
checkLogin()which accepts a url string from the parameter
statewhich will be the previous route the user came from if the guard check is false, not permitting the user to be logged in.
we can now update our login component and tie in the new functionality.
Currently our file
login.component.ts looks like this: