Developer Programs

Learn

Docs

Unsaved Changes

Components > Editing Data > Unsaved Changes
Use this component to...
Prompt the user before unsaved changes are lost

Overview

When the user edits data in a form within your application, the changes they make to the form are not saved until the user presses the Save button.

If the user attempts to navigate away from the form before saving their changes, it’s important for the application to warn the user before any unsaved changes are lost.

In many cases, we should also warn the user of unsaved changes when they press the Cancel button while editing a form.

There are two scenarios in which we need to display the unsaved changes dialog:

  • The user is navigating away from an unsaved edit form that does not have validation errors
  • The user is navigating away from an unsaved edit form that has validation errors

In each of these scenarios we display the unsaved changes warning in a dialog box, with slight differences between what is displayed in the dialog box. Each scenario is described below.

Unsaved changes in a form without validation errors

If the form has no validation errors, the user’s unsaved changes are able to be saved, so the unsaved changes dialog box includes the following:

  • The dialog box title is “Do you want to save your changes?”
  • The dialog box content is the text “Your changes will be lost if you don’t save them.”
  • The dialog box has 3 buttons:
    • A “Save Changes” button with primary styling
      • The user presses this button to save their changes, then either navigates away from this view or cancels the form changes, depending on the situation.
    • A “Don’t Save Changes” button with destructive styling
      • The user presses this button to abandon their changes, then either navigates away from this view or cancels the form changes, depending on the situation.
    • A “Continue Editing” button with secondary styling
      • The user presses this button to keep their changes and continue working in the current view.
Dialog warning user of unsaved changes
Unsaved changes dialog when the form does not contain validation errors

Unsaved changes in a form with validation errors

If the form has validation errors, the user’s unsaved changes cannot be saved as-is, so the unsaved changes dialog box includes the following:

  • The dialog box title is “Unsaved Changes”
  • The dialog box content is the text “Your changes have not been saved.”
  • The dialog box has 2 buttons:
    • A “Lose Changes” button with destructive styling. The user presses this button to abandon their changes, then continue with (a) navigating away from this view or (b) canceling the form changes, depending on the situation.
    • A “Continue Editing” button with secondary styling. The user presses this button to keep their changes and continue working in the current view.
Dialog warning user of unsaved changes when the form contains validation errors
Unsaved changes dialog when the form contains validation errors

Development

Web component development

Implementation

Rather than having to build your own unsaved changes detection and warning mechanism, Responsive UI provides you with a service, route guard, and specialized dialog box component to help simplify the process and provide a consistent user experience for handling unsaved changes.

The unsaved changes mechanism is intimately tied into the Angular router, so this mechanism requires the use of Angular.

You will need to build your own unsaved changes handling for UI technologies other than Angular.

Begin by importing the JhaUnsavedChangesModule and the JhaUnsavedChangesGuard into your application. Apply the JhaUnsavedChangesGuard function as part of the Route object in the router configuration and add the JhaUnsavedChangesModule.forRoot() entry to your imports array.

Import the module
// import into app.module
import { JhaUnsavedChangesModule } from '@jkhy/responsive-ui-angular/jha-unsaved-changes';
import { JhaUnsavedChangesGuard } from '@jkhy/responsive-ui-angular/jha-unsaved-changes';

const routes: Routes =
    [
        { path: '', redirectTo: '/Home', pathMatch: 'full', canActivate: [AuthenticationGuard] },
        { path: 'EditCustomerDetails', component: EditCustomerDetailsComponent, canDeactivate: [JhaUnsavedChangesGuard] },
        ....
    ];

@NgModule({
    imports: [
        ...
        JhaUnsavedChangesModule.forRoot(),
        ...
    ]
})

export class AppModule(){}

In the TypeScript file that contains your form, import the JhaUnsavedChangesService service and add it to the constructor. Add a canDeactivate method that, when your form has unsaved changes, calls the promptUnsavedChangesDialog method which will return a result of ‘Save’, ‘DontSave’, or ‘ContinueEditing’ depending on what the user selected.

If there’s a scenario where the form can fail validation, and therefore saving changes should not be an option, pass the form’s validation status as an argument to the promptUnsavedChangesDialog method call. If the value passed is false, the unsaved changes dialog will let the user know the changes have not been saved, and only provide them with options to Lose Changes or Continue Editing; the promptUnsavedChangesDialog call will return a value of either ‘LoseChanges’ or ‘ContinueEditing’.

Unsaved changes handling
import { Component } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms';
import { lastValueFrom } from 'rxjs';
import { JhaUnsavedChangesService } from '@jkhy/responsive-ui-angular/jha-unsaved-changes';

export class UnsavedChangesComponent {

    public editForm: FormGroup = new FormGroup({
        ...
    });

    constructor(private unsavedChangesService: JhaUnsavedChangesService) {}

    // canDeactivate for unsaved changes guard
    public async canDeactivate() {
    if (this.editForm.dirty) {
        const promptResult =  this.unsavedChangesService.promptUnsavedChangesDialog(this.editForm.valid);
        
        let promptUserResult = await lastValueFrom(promptResult);
        
        if (promptUserResult === 'Save') {
            // Save changes in database, then return true
            return true;
        } else if (promptUserResult === 'DontSave') {
            //  Dont save changes
            return true;
        } else if (promptUserResult === 'LoseChanges') {
            // Losing changes
            return true;
        } else {
            // Returning to editing without leaving page
            return false;
        };
    } else {
        return true;
    }
}

Angular wrapper development

Implementation

Rather than having to build your own unsaved changes detection and warning mechanism, Responsive UI provides you with a service, route guard, and specialized dialog box component to help simplify the process and provide a consistent user experience for handling unsaved changes.

Begin by importing the JhaUnsavedChangesModule and the JhaUnsavedChangesGuard into your application. Apply the JhaUnsavedChangesGuard function as part of the Route object in the router configuration and add the JhaUnsavedChangesModule.forRoot() entry to your imports array.

Import the module
// import into app.module
import { JhaUnsavedChangesModule } from '@jkhy/responsive-ui-angular/jha-unsaved-changes';
import { JhaUnsavedChangesGuard } from '@jkhy/responsive-ui-angular/jha-unsaved-changes';

const routes: Routes =
    [
        { path: '', redirectTo: '/Home', pathMatch: 'full', canActivate: [AuthenticationGuard] },
        { path: 'EditCustomerDetails', component: EditCustomerDetailsComponent, canDeactivate: [JhaUnsavedChangesGuard] },
        ....
    ];

@NgModule({
    imports: [
        ...
        JhaUnsavedChangesModule.forRoot(),
        ...
    ]
})

export class AppModule(){}

Within your app.component.html, add the jha-unsaved-changes-dialog-box component inside of your jha-app component.

Adding unsaved changes dialog box to app.component.html
<jha-app>
    <main-header class="rui-main-header"></main-header>
    <main-nav class="rui-main-nav"></main-nav>

    <jha-unsaved-changes-dialog-box></jha-unsaved-changes-dialog-box>
</jha-app>

In the TypeScript file that contains your form, import the JhaUnsavedChangesService service and add it to the constructor. Add a canDeactivate method that, when your form has unsaved changes, calls the promptUnsavedChangesDialog method which will return a result of ‘Save’, ‘DontSave’, or ‘ContinueEditing’ depending on what the user selected.

If there’s a scenario where the form can fail validation, and therefore saving changes should not be an option, pass the form’s validation status as an argument to the promptUnsavedChangesDialog method call. If the value passed is false, the unsaved changes dialog will let the user know the changes have not been saved, and only provide them with options to Lose Changes or Continue Editing; the promptUnsavedChangesDialog call will return a value of either ‘LoseChanges’ or ‘ContinueEditing’.

Unsaved changes handling
import { Component } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms';
import { lastValueFrom } from 'rxjs';
import { JhaUnsavedChangesService } from '@jkhy/responsive-ui-angular/jha-unsaved-changes';

export class UnsavedChangesComponent {

    public editForm: FormGroup = new FormGroup({
        ...
    });

    constructor(private unsavedChangesService: JhaUnsavedChangesService) {}

    // canDeactivate for unsaved changes guard
    public async canDeactivate() {
    if (this.editForm.dirty) {
        const promptResult =  this.unsavedChangesService.promptUnsavedChangesDialog(this.editForm.valid);
        
        let promptUserResult = await lastValueFrom(promptResult);
        
        if (promptUserResult === 'Save') {
            // Save changes in database, then return true
            return true;
        } else if (promptUserResult === 'DontSave') {
            //  Dont save changes
            return true;
        } else if (promptUserResult === 'LoseChanges') {
            // Losing changes
            return true;
        } else {
            // Returning to editing without leaving page
            return false;
        };
    } else {
        return true;
    }
}

Design

Figma design

Figma design info
You can find this component in the Components - Dialog Box page in the Figma UI Kit.
Dev ComponentDesign Component Name
Modal backdropRUI / Modal / Backdrop
Unsaved changes dialogRUI / Forms / Unsaved Changes Dialog
The Unsaved Changes pattern displays a special dialog box that notifies the user that they are navigating away from a view that has unsaved changes.

The user’s changes may or may not be able to be saved, depending on circumstances.

  • If the user’s changes can be saved, the unsaved changes dialog box offers 3 options:
    • The Save option saves the user’s changes and continues the navigation away from this view.
    • The Don’t Save option abandons the user’s changes and continues the navigation away from this view.
    • The Continue Editing option abandons the navigation and keeps the user in the current view without saving the changes.
  • If the user’s changes cannot be saved, the unsaved changes dialog box offers 2 different options:
    • The Lose Changes option abandons the user’s changes and continues the navigation away from this view.
    • The Continue Editing option abandons the navigation and keeps the user in the current view without saving the changes.

All dialog boxes display a translucent modal backdrop behind them, which darkens the background. Add this component first. Resize it to cover the entire view. Lock the modal backdrop so you can drag other components on top of it.

Then drag an unsaved changes dialog component onto the modal backdrop and center it within the view.


Adobe XD design

Adobe XD design info
You can find this component in these artboards in the Adobe XD design samples:
  • Sample App - Unsaved Changes
Dev ComponentDesign Component Name
Modal backdropJHA / Modal / Backdrop
Unsaved changes dialogJHA / Forms / Unsaved Changes Dialog
The Unsaved Changes pattern displays a special dialog box that notifies the user that they are navigating away from a view that has unsaved changes.

The user’s changes may or may not be able to be saved, depending on circumstances.

  • If the user’s changes can be saved, the unsaved changes dialog box offers 3 options:
    • The Save option saves the user’s changes and continues the navigation away from this view.
    • The Don’t Save option abandons the user’s changes and continues the navigation away from this view.
    • The Continue Editing option abandons the navigation and keeps the user in the current view without saving the changes.
  • If the user’s changes cannot be saved, the unsaved changes dialog box offers 2 different options:
    • The Lose Changes option abandons the user’s changes and continues the navigation away from this view.
    • The Continue Editing option abandons the navigation and keeps the user in the current view without saving the changes.

All dialog boxes display a translucent modal backdrop behind them, which darkens the background. Add this component first. Resize it to cover the entire view. Lock the modal backdrop so you can drag other components on top of it.

Then drag an unsaved changes dialog component onto the modal backdrop and center it within the view.


Support options
Have questions on this topic?
Join the Responsive UI team in Microsoft Teams to connect with the community.
See something in this page that needs to change?
Send us feedback on this page.
Last updated Mon May 1 2023