Filling out a form, especially one with many fields, can be tedious. Losing everything you’ve entered because you may have tapped or clicked a link by mistake is frustrating! What if you could warn the user of unsaved changes to the form? Let’s learn how!
Create Route Guard
Each page that you navigate to in an Angular application is considered a route. Each route can be protected using a route guard. If you want to protect the user from navigating away from the current route, you can use the CanDeactivate route guard.
A route guard is really just a service. First, you’ll need to import the CanDeactivate interface.
import { CanDeactivate } from '@angular/router';
Next, import the component where your form is located.
import { FormComponent } from 'path/to/component';
Now let’s create the service that implements the CanDeactivate interface. Pass in the component as an argument. This will give us access to all of the component’s properties and methods.
We need to return a boolean, where true will allow the user to navigate away and false will make the user stay put!
@Injectable()
export class FormGuard implements CanDeactivate<FormComponent> {
canDeactivate(component: FormComponent): boolean {
return true;
}
}
We should return false if anything in the form has changed. Luckily, Angular makes this easy for us because the FormGroup provides a property called dirty. A form is considered dirty if a value has changed.
If the user changed any value and then tries to navigate to a different route, let’s ask if they really want to leave. We can use the browser’s confirm dialog, which will return a boolean. Let’s add that check into the guard.
@Injectable()
export class FormGuard implements CanDeactivate<FormComponent> {
canDeactivate(component: FormComponent): boolean {
if (component.form.dirty) {
return confirm('Are you sure you want to navigate away and lose changes to the form?');
}
return true;
}
}
Apply Route Guard
Now that our route guard is complete, we need to provide it.
Within the module where the form component is associated, import the guard.
import { FormGuard } from 'path/to/guard';
Then add the guard to the providers property.
providers: [
FormGuard
]
In the routing module where the routes are defined, import the guard.
import { FormGuard } from 'path/to/guard';
Finally, add the guard to the route itself.
{
path: 'contact',
canDeactivate: [FormGuard],
component: FormComponent
}
Test Route Guard
Navigate to the form component and change a value in one of the fields. Now try navigating to another page within the app. Notice you get prompted with the dialog! You have successfully warned the user they may lose what they changed in the form! If you cancel the dialog, you’ll stay where you are, but if you say Ok, then you’ll navigate away and lose whatever you entered in the form.
Keep in mind that this only works when navigating within the Angular application. It does not check the guard when navigating to a different web page or if the tab or browser is closed.
Visit our website at https://nightwolf.dev and follow us on Twitter!
Top comments (2)
Great idea to catch this event on route change !
Can it somehow be implemented if the route doesn’t change ? (For example when the form is inside of a modal)
If the user closes the modal by mistake, you could listen for that modal close event and if the form is considered dirty, warn the user at that moment.