6
votes

I am using Ember 1.7 and have a model with a validation on it.

Using the input helper, I'm binding an action to the on="key-press" trigger.

In the action fired (within my controller) I'm calling this.get('myModalInstance').validate() and I have handlers setup for pass and fail.

What's odd is that the validation seems to fire with the previous value I've typed.

So if my validation says numericality: { greaterThan: 0, lessThanOrEqualTo: 90 } when I type 9, it validates ok, when I type in 91 it validates ok, and when I type in 911 it fails validation.

This seems one key press too late as far as I can see. Is this a known / common issue? Are there are tips for avoiding this issue?

EDIT I should add that I've also tried to bind my validation failure css class to the errors object for a field like this:

{{input value=myValue classBinding=":form-input myValue.errors:validation-failure"}}

Which is displaying strange behaviour (such as sometimes not applying the class at all, sometimes applying it when I'm expecting (such as deleting the contents on an input which has presence: true set) and sometimes validating when I change a different control on the form.

1
I've found out that key-press fires before the value has changed (hence my confusion) and for some reason key-up & key-down don't fire at all :/dougajmcdonald

1 Answers

2
votes

You don't need a keypress event, if you want to validate some value (or few) when they updated. Use observer (read "Observers and asynchrony" section thoroughly, it's very important and shows how to avoid such lags) instead: observe changes to fields you are interested in and validate.

Or, if you want to use one of jquery validation plugins, you can create a component, call it validated-form for example, and use a jquery plugin for validation. These plugins usualy handle all needed events themself. Simple version of such component (should work with this plugin):

import Ember from 'ember';

export default Ember.Component.extend({
    tagName: 'form',
    onSubmit: null,
    validationRules: {},
    validationMessages: {},
    didInsertElement() {
        const form = this.$();
        form.validate({
            submitHandler: () => {
                if (this.get('onSubmit')) {
                    this.sendAction('onSubmit');
                }
            },
            rules: this.get('validationRules'),
            messages: this.get('validationMessages')
        });
    }
});

And in template you use it like this:

{{#validated-form validationRules=validationRules}}
    Form fields here
{{/validated-form}}

If you are interested in reasons why your solution doesn't work, I believe that's because ember's input component uses input event to update binded value, and input event is being fired after keypress