In the next part of the Angular series, we want to adapt our to-do list a little architecturally. We implement a ToDoService, add a second page and control it under certain conditions.
Service architecture
In software development, it is generally desirable to keep everything as variable and modular as possible.
This also applies to Angular, so far we had the list with our to-do items in ToDosComponent
, we now want to adapt and outsource this.
Real World Case:
The architecture would be similar for a real application, only the data storage would be in an external database, e.g. B. can be done via the REST interface.
First we want to create our first service in Angular via CLI:
|
|
What does this service have to be able to do? He should:
- Save the list of To Do Items
- Return the list of To Do Items
- Add a new to do item
- Check off a to do item
- To delete a to do item
- Check whether all to-do items are done
We use the LocalStorage
functionality of Angular to save our To Do list, this allows us to persist the data and to be able to read it out again.
We use the annotation Injectable
to register this class as a service.
Learn more about the advantages of this service architecture in our Angular pro tips.
Our fully implemented ToDoService
can be seen below:
|
|
Now we have created an encapsulated logic class with all the business logic for our to-do items. We can now inject this service as a dependency via the constructor of every TypeScript class. So we have an independent, reusable class that we can address as often as we want.
In the following you can see that we still need the variable toDos
in our ToDosComponent
in order to be able to access it in the template.
Replace the content of your ToDosComponent
class with the following code:
|
|
Another big advantage of this architecture is that the data source and template components are separate from each other.
For example, we could implement an endpoint to get the data and would only have to adapt our ToDoService
, all components remain the same.
The second side
But now we want to bring some life to our application, we are creating a second page!
The aim is to be able to show the user a page that can only be called up when all to-do items have been checked.
A page in Angular is basically nothing else than a component, as we know, we create it as follows:
|
|
The HTML in this case should be kept very simple, the user should only be shown a message:
|
|
Now we could integrate the component as well as our To Dos component via selector, but we really want to have a URL to call up the page.
routing
Angular routing allows us to do just that: you bind a component to a path which can then be called up in the browser.
We do all configuration in the app.module.ts
file, there all URLs including their components are defined.
In our case we say that the ToDosComponent
should be rendered by default. The path “success” then leads to SuccessComponent
.
|
|
Another change we have to make in order to be able to use routing at all is to adapt our app.component.html
template.
The selector of ToDosComponent
is currently permanently entered there, we have to replace it with the selector of the Angular router module:
|
|
Our new component can now be successfully accessed via the /success
URL.
It is important to note that the order of the routes must be correct, a so-called first match wins
strategy is used.
This means that a wildcard routes (typically leading to a 404 page) must be at the end.
Of course, the RouterModule offers other options such as sending parameters, redirects, nested routes and many more.
Now we want to automatically redirect to the url /success
if all todos are checked off, for this use the Angular class Router
.
At every Complete Event, we check whether all to-dos have already been completed.
|
|
Guard
But how do we ensure that the SuccessComponent can only be called when all to-do items have been checked?
Of course, we were able to implement logic in the component itself and fire a redirect in the event of an error, but Angular also offers us a leaner solution here.
A so-called Guard
allows us to carry out certain actions or to link access to a route to a condition.
There are basically five different types of guards:
CanActivate
- Checks whether the route can be calledCanActivateChild
- Checks whether a child route can be calledCanDeactivate
- Checks whether the current route can be leftResolve
- Request and prepare data before a route is calledCanLoad
- Checks whether children can be loaded, useful for lazy loading with multiple modules
To achieve our goal, all we need is CanActivate Guard
, which we can create via Angular CLI as follows:
|
|
Now we want to implement our guard in such a way that it redirects back to the root page in the event of an error.
Here again the great advantage of the service architecture comes to the fore, since we can inject and use our ToDoService
as a dependency.
Using the class Router
we can navigate programmatically to the root page.
|
|
Now we only have to assign the guard to a route so that it is also used.
|
|
Another useful feature is that the guards can be specified as an array and a route can only be called if all guards return true. In addition, a guard can be used as often as required.
Now we have successfully created a second page in our service-based ToDo application. A guard allows us to control access rights for this page.
The complete ‘b-nova ToDo-List’ project can be found on GitHub.
Stay tuned!
This text was automatically translated with our golang markdown translator.