Series: Form Validations with ember-validations

Form Validation with ember-validations

Published on Aug 12, 2015

ember-validations make form validations easy...er.

In this episode we set up the library, work with some basic examples, and discuss different strategies for how to handle your validations.


Links

Code

Add ember-validations (2.0.0-alpha.4) to your package.json dependencies

"ember-validations": "2.0.0-alpha.4",

You can create a validations hash with various options. The hash can be on a controller, a component, or even a mixin which you include in multiple controllers or components.

import Ember from 'ember';
import EmberValidations from 'ember-validations';

export default Ember.Mixin.create(EmberValidations, {
  validations: {
    "model.title": {
      presence: true,
      length: {minimum: 5, maximum: 300}
    },
    "model.seconds": {
      numericality: true
    }
  },
});

You can then validate on an action (before saving)

import PostValidations from 'ember-admin/mixins/validations/post';

export default Ember.Controller.extend(PostValidations, {
  actions: {
    save(){
      //...
      this.validate().then(()=>{
        model.save().then(()=>{
          this.transitionToRoute('post.show', model)
        })
      }).catch(()=>{
        console.log(this.get("errors"))
      })
    }
  }
}

Transcript

Form Validation is an extremely common frontend use case, and today we’re going to show how to do it with the ember-validations library.

So ember-validations is currently in 2.0.0-alpha, and I usually don't make screencasts about alpha libraries, but this is a widely used library, it’s still very useful, and it’s been in alpha for 10 months, so I’m not going to wait longer. If the 2.0 version comes out, I will try to revise this episode.

So to start, you put ember-validations in your package.json, and then you run npm install. Once it’s installed, you go and you find the controller where you want to run the validations. In this case, we’re doing the posts/edit controller, and then you import the validations. Then you include it as a mixin, then within the controller you can make a validations hash. Within this hash, we’ll make another hash for each of the properties that we want to validate. In this case we’ll have a title. We’ll make sure that its presence is true, and then we’ll make sure that its length is a minimum of 5, and a maximum of 300, and that also will be a hash.

Next, we’ll want to run our validations when we’re saving. So here, we have our save, and before we call save on the model, we’ll want to validate. So we can say this.validate, and then if it does validate, it’ll run whatever’s here. But if it doesn’t validate, if the validation returns false, then it’ll run whatever’s in the catch block. So let’s take our saving action that we were using before and we’ll run that if the validations pass. Then if the validations fail, we’ll put an error. For now, we’ll just do a console.log. Let’s see this in action.

We’ll take our title and just delete it, and that when we save, notice it didn’t save, it didn’t redirect us like it normally would. Instead, it gave us this error. So this error is a hash with title, the title is an array with two different errors, one for can’t be blank and one for length, is too short. Notice those correspond directly to our validations hash.

So this is all well and good, but there is a problem. That is that the ObjectController is going away. It’s being deprecated and then taken out completely. So in the future, we won’t have ObjectController, and that’s required for EmberValidations to work right out of the box. There are multiple ways to get around this. The first is just to take every property, wrap it in quotes, and then do model. before you give the property key. That’ll change up your error a little bit. You have to go through the model before you can get to the properties, but not too much, a pretty small change. So that fix works for now, but then we run into another problem. What if we want to create a new post? We’ll see when we try to hit save that the validations from edit post are not carrying over. So our 'Title' is empty, and when we hit 'Save', and it saves it.

So one way to fix this would be to copy the validations. So you just take this, copy it, and paste it into the new controller, and then put in all our boilerplate up top. But once you get more validations than just one, this is not that great of an option. So instead of that, let’s create a mixin. Now we’ll use that mixin to put it into both of these. We’ll start by getting the validations and including that in the mixins. We’re getting a mixin in our mixin. And then we’ll copy over the validations from our controller and put those in the mixin. Then in our controllers, we’ll take our import of the EmberValidations, replace it with our import of our validations mixin, of our specific validations mixin. And we’ll go ahead and do this with the new controller as well. We’ll also have to make sure to add in the validation logic in the save action.

So we’ll try this out. We’ll go to a new post and we’ll hit save, and it gives us the error. But if you dig a little deeper, you have a... you’ll put in the title and you hit save again, and you’ll get the same error, and the reason is because in my new post, I don’t have it labeled model. I have something called newPost, and that’s the object that I have. And so my validation is automatically in our mixin. It’s going off of model. How can we fix that?

The most Ember-y way to fix this is to make a route, and in this route we’ll define the model. This model will take the place of newRoute, so take this and just return a new hash. That’ll be our model. And we replace all references to newPost with model, and we’ll have to do this in the template as well, and then it should work nicely. It accepted it, and with a blank one it will reject it.

So when we’re using this technique, the thing that you want to validate has to be called model. There’s another way to share validations, and that’s to put them on the model themselves. So we’ll take these validations, we’ll put them on the model, we’ll do the import of the Ember validations library into the model, and then we won’t have to mix it in to our controller. All we’ll have to do is just instead of calling this.validate, we’ll call model.validate.

So putting it on the model is fairly simple, but there are some downsides. The first is that validations are automatically run when the object is created. So if you put it on the Ember data model, then whenever you’re loading all your stuff from the server, it’ll run those validations then. And that means if you load a lot of stuff from the server, it can get really slow especially if you have a lot of validations. I was working with a client where it quadrupled their time to first page load. So if you’re loading a lot of objects and you have a lot of validations, don’t put it on the actual model. It also has the downside of it’s less easy to change stuff. When you’re using a mixin, then on the controller you can have a validation hash that overwrites part of the mixin.

So today we talked about how to use form validations with ember-validations. We went over where to put your validations. You can put them on the controller, either directly or through a mixin, or you can put it on the model. I recommend putting it on the controller through a mixin. Then we talked about how to reference the model in a validation. We can use the ObjectController which is unfortunately going away, we can use model.key which is a little wordy but it works, or we could put it on the model. Right now it looks like the best option is model.key. Hopefully, we’ll be getting some better options soon.

But that’s not all there is to validations. In coming weeks, we’ll talk about how to display the validation errors to your users, how to use advanced validations beyond just presence or length, and how to do conditional validations which is a really cool feature. I’ll see you then.

Form Validations with ember-validations

Subscribe to our mailing list