Series: Editing and Validating Forms with ember-changeset

Are You Sure You Want To Leave This Page?

Published on Aug 17, 2016

We've all had it happen- you spend 10 minutes filling out a form just perfectly, and then you accidentally click to a new page... losing all your work!

This videos shows you how to implement a common solution to that problem- a confirmation popup. We'll work with the ember-changeset code from the last two episodes, but the core of technique should be generalizable to apps without ember-changeset.


Links

Code

//routes/monsters/monster/edit.js
import Ember from 'ember';
import Changeset from 'ember-changeset';

export default Ember.Route.extend({
  setupController(controller, model){
    controller.set('changeset', new Changeset(model))
  },
  actions: {
    willTransition(transition){
      if(this.get('controller.changeset.isDirty')){
        if(!confirm('You have unsaved changes.  Are you sure you want to leave this page?')){
          transition.abort();
        }
      }
    }
  }
});
//templates/monsters/monster/edit.hbs
{{monster-form changeset=changeset save=(action "save") rollback=(action "rollback")}}

Transcript

We’ve got Ember changeset working pretty well, but we’re not protecting the user from their own mistakes. Let’s say I click on another monster. We just lost the progress that I’d been making on that form, which wasn’t too bad right there. But for longer forms, this could be a big deal. It would be great if when we’re about to leave this route and we had unsaved changes, it would confirm to make sure that’s what we meant to do. Luckily, we can make this with Ember. We’re going to be using Ember changeset for part of this, but it can be done with just Ember data as well.

So first we’re going to generate the route. And this route in particular is monsters/monster/edit. In this route, the core of what we’ll be doing is taking the willTransition hook, and we’re going to be using this in order to check whether there are things still dirty, and then it’s going to check whether the user wants to confirm. And then if the user cancels, we’re going to abort the transition.

The first thing we’ll do is get the isDirty property. And if you’re using just plain old Ember data without Ember changeset, then that property is there as well, and so a lot of this video will still apply. But since we are continuing on from the last two videos, we will be referencing Ember changeset.

So what we currently have going is we’re passing down the model and we’re transforming it in the handlebars into the changeset. And then that changeset is being passed back up to the save and rollback actions on the controller. And that’s great,] that’s data down, actions up. But when we want to access the changeset object and the isDirty property on it, we can’t have it hidden away in the component. We have to get it on the controller and doing two-way binding.

So first we’re going to assume here that we have something called changeset in our controller. Then we’re going to go about creating that. We’re going to use the setupController hook in our router. And the setupController comes with two arguments, controller and model. And so we can call controller.set, and here we can just simply set the changeset. And we’re going to call a new Changeset made from that model. Now to do that, we have to import the Changeset from ember-changeset. And so this is doing in our JavaScript what the handlebars helper had been doing in our handlebars before.

If we try this now, then we’ll see that it seems to be working. Everything is showing up here correctly but not over here. But when we hit ‘Save’, it’ll transition to the undefined route. So that’s what it’s getting as the id, is undefined. And for some reason, our change requires us in our transition to route from feeding in the model to feeding in the changeset id. And when we make that change, then we will find that everything’s working again.

So that’s the setup. What about the actual feature? So first we’ve got to check if it’s dirty so we can get the controller, and now we have the changeset on the controller, then we have the isDirty property on the changeset. And then we want to run a JavaScript confirm, and it’ll say It seems that there are some unsaved changes. Are you sure you want to leave this page? And then go ahead, and when you do this, there will be an ‘OK’ box which will return a true and a ‘Cancel’ box which will return a false, and if we cancel then we want to abort. So we want to add this not here. So if they abort, if this confirm returns false, then we call transition.abort.

Let’s try this out. We will be changing this up and then we click somewhere else and there it goes. It asks us if we want to leave this page. And we can hit ‘Cancel’ and we won’t leave. But if we hit ‘OK’, then we will leave and lose our work. And of course if we don’t change anything, then we can click elsewhere with ease. So there we go. There is a common and very, very useful feature. I hope you join us in the next episode, where we start talking about validations.

Editing and Validating Forms with ember-changeset

Subscribe to our mailing list