Ever filled up a form with a bunch of information and then accidentally navigated away and lost all data? Well, that’s frustrating. However, as a developer, it might be tricky to implement such functionality. This post is a practical guide to implementing is dirty checking using Vue, Vue Router and Typescript.

TL;DR

Code is available on GitHub.

Expected behavior

In a Vue app with Vue Router, when a user modifies data in a form and any navigation to another route occurs, the user should be notified and have the ability to cancel navigation.

Is Dirty Demo Demo app running

FormEdit.vue

I like to wrap this kind of functionality in base components that can be reused across multiple forms. This is specially true for IsDirty and IsBusy. For this demo I created a FormEdit component.

The FormEdit component will be added inside a template to wrap the form controls. It will also request that the entity being edited is passed to it so it can track changes using a @Watch. Finally, it exposes two methods to control is dirty and navigation: resetDirty will be called anytime the consumer deems the entity to be clean; ensureNotDirty will be called anytime navigation is detected from its parent component registered as a route in Vue Router.

Home.vue

This component contains the actual form with a couple of fields. It uses the form-edit as a wrapper around the form fields as indicated in the previous section. On mounted we load the data and mark the form as not dirty. This is required because by modifying the entity property the FormEdit thinks the form is dirty. Finally, this component has a hook for beforeRouteLeave. This hook is what we need to intercept and allow or cancel the navigation. The heavy lifting is done by FormEdit but Vue Router requires that the route component has the hook method meaning that we intercept it here and pass the values on the FormEdit.

Can we improve this?

Of course! The number one thing you might want to do is to replace the simple dirty tracking with an actual compare of the old/new entity so you only prompt the user if they have changes pending. Once the user changes the record back, you can disable save button and such.

Got some feedback for me? Hit me up on twitter!

Cheers, Lucas