DEV Community

Cover image for Warn User Of Unsaved Changes to Angular Form
nightwolfdev
nightwolfdev

Posted on • Updated on • Originally published at nightwolf.dev

Warn User Of Unsaved Changes to Angular Form

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';
Enter fullscreen mode Exit fullscreen mode

Next, import the component where your form is located.

import { FormComponent } from 'path/to/component';
Enter fullscreen mode Exit fullscreen mode

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;
  }
}
Enter fullscreen mode Exit fullscreen mode

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;
  }
}
Enter fullscreen mode Exit fullscreen mode

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';
Enter fullscreen mode Exit fullscreen mode

Then add the guard to the providers property.

providers: [
  FormGuard
]
Enter fullscreen mode Exit fullscreen mode

In the routing module where the routes are defined, import the guard.

import { FormGuard } from 'path/to/guard';
Enter fullscreen mode Exit fullscreen mode

Finally, add the guard to the route itself.

{ 
  path: 'contact',
  canDeactivate: [FormGuard],
  component: FormComponent
}
Enter fullscreen mode Exit fullscreen mode

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!

Oldest comments (2)

Collapse
 
pinich profile image
Pini Cheyni

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)

Collapse
 
nightwolfdev profile image
nightwolfdev

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.