Series: Form Validations with ember-validations

Custom Validators with Multiple Keys

Published on Aug 28, 2015

Having a validator that just relies on one property isn't cool. You know what's cool? Relying on two properties. Even three properties.

ember-validations lets you be cool, using dependentValidationKeys.


Links

Code

You want to display an error if one or the other checkboxes is checked, but not both:

<p>Boolean logic, that'll catch'em!</p>
{{input type='checkbox' checked=xor1}} xor {{input type='checkbox' checked=xor2}}
{{display-errors errors=errors.xor showErrors=showErrors}}

So you set the validation to xor, giving it two different keys

validations: {
  xor: {
    xor: {key1: 'xor1', key2: 'xor2'}
  }
}

Then you create the xor validator. Note we're pushing objects onto the dependentValidationKeys array.

import Base from 'ember-validations/validators/base';

export default Base.extend({
  init: function(){
    this._super()

    this.dependentValidationKeys.pushObject(this.options.keyOne);
    this.dependentValidationKeys.pushObject(this.options.keyTwo);
  },
  call: function(){
    var one = this.model.get(this.options.keyOne)
    var two = this.model.get(this.options.keyTwo)
    if((one && two) || (!one && !two)){
      this.errors.pushObject('Must be one or the other')
    }
  }
});

The more general case (Select X of the options) can be found here

Transcript

Welcome back to EmberScreencasts. In today’s episode, we’re going to be talking about custom validations that have multiple keys.

So our client is getting paranoid again, and so he decided to add some more validations. We thought: alright, boolean logic, that’s something humans are great at and computers are terrible at. But just in case you’re a computer, I’ll explain what a xor function is. Basically it means one or the other has to be true. It can’t be both of them and it can’t be neither of them. Let’s look at how this is currently implemented.

So in the template we have two inputs. Their checkbox is going to xor1 and xor2. And then the errors are going to xor. So in our controllers validation hash we have the xor key, and then we’re doing an acceptance validation. That means that the xor value must be 1 or true. So here we have our xor computed property which is doing our xor using xor1 and xor2. Now of course this works, but it would be better if we didn’t have to use a computed property here. Instead we could just do this. It would make our intention a lot more clear.

Let’s go ahead and create a validator called xor. We’ll create it in the local validators directory. And then we’ll import from base like we did with email. Then we’ll create our call function. So we’ll be grabbing two different properties this time, and neither of them are directly the property that we’re calling this on. So we’ll call get on this.options.keyOne and this.options.keyTwo. Then we’ll do our comparison, and if it’s not what we want, then we will push the errors.

So in our specific case, keyOne and keyTwo are xor1 and xor2, and so we’ll be comparing the values of xor1 and xor2 here. But there’s a problem. When we change these, it doesn’t recalculate. Why is that? Well, the validator is automatically set up to watch whichever property you’ve put it on. So we’ve put this xor validator on the xor property. And so anytime the xor property changes, then this will get called again.

However, changing xor1 or xor2 doesn’t change this property, so we’ll need to find another way to trigger it. We’ll do this through the init function. So the init function... of course we’re going to have to call super in order to not overwrite what’s coming before. But then we can add to dependentValidationKeys. So adding to the dependentValidationKeys makes it so that whenever any of these change, call will be recalculated. So let’s see this in our application. Now when we change it, it updates.

So to review, in a custom validation you can create custom options and then you can have the things corresponding to those custom options watched so that your call will be called every time one of those changes. This opens up a much bigger array of things that you can do.

Speaking of arrays, you can also make your keys into arrays. Here we have the correctSelections property, and we’re going to use the custom-built selectSome validator. And as you can see we’ve got an array of selections, s1, s2, and s3, and we’ve set the correctLength as 2. What does that mean? Well, here in our selectSome we’ve gone over each of the things in the selections array and added them as dependentValidationKeys. And then in our call, we filtered through those and grabbed the ones that are selected. Then if that amount is less than the correct length, we say Select another. If it’s more than the correct length, we say Too many selected. And this works great.

So xor and selectSome are kind of [04:38] niched, but they’re not as general as length or confirmation. However, I hope you can see the great swath of possibilities that are open before you to make almost any validation that you can imagine. Use it wisely and I’ll see you next week.

Form Validations with ember-validations

Subscribe to our mailing list