aurelia / validatejs

Enables expressive validation using decorators and/or a fluent API.
MIT License
22 stars 23 forks source link

Validate doesn't work when bind to an object #77

Closed cyberhck closed 8 years ago

cyberhck commented 8 years ago

Context

I'm trying to use validate on a project, which worked fine when I just bind validator to this like:

this.validator = new Validator(this)
            .ensure('Login').required().length({minimum: 3, maximum:10});
this.reporter = ValidationEngine.getValidationReporter(this);

Which works fine, but when I try to bind it to a different object like this:

this.validator = new Validator(this.user_data)
            .ensure('Login').required().length({minimum: 3, maximum:10});
this.reporter = ValidationEngine.getValidationReporter(this.user_data);

It doesn't work. Steps to reproduce:

Error message being displayed on UI like when we fill invalid entry on decorators

Actual

No error message on UI, but error message is being logged in console.

I also tried debugging and went through a little bit of source code, and checked ValidationRenderer.prototype.renderErrors function, but looks like if I bind the data to a object property instead of a normal property, the function renderErrors is not even called, maybe this info can help in debugging.

I've a hunch that this must be broken due to recent changes since sample app should have been working before.

Below is a screenshot attached of what it looks like in my PC

image

MaximBalaganskiy commented 8 years ago

:+1: It is indeed a bug - the validation behavior expects a reporter on the view model but the validator needs a reporter on a POJO. If, in a constructor, I create a reporter for the view model then validator is obviously not using it.

MaximBalaganskiy commented 8 years ago

the workaround is to set a reporter property on a view model like this

this.__validationReporter__ = ValidationEngine.getValidationReporter(this.stable);
arjyamishra commented 8 years ago

In addition to the issue raised by @cyberhck

  1. Is it necessary to instantiate the reporter and observer in the constructor of the view model. I have instantiated them inside attached() method. Will it make any difference.

this.__validationReporter__ = ValidationEngine.getValidationReporter(this.entity); this.observer = this.__validationReporter__.subscribe(result => { this.errors = result; console.log(result); });

  1. Also, In my project input controls are not kept directly on the fluent.html (as shown in the sample app) but on a nested level to load entities dynamically with different properties.

I have added validate binding option to the input controls value.bind="item.Id & validate" as described in http://patrickwalters.net/aurelia-validate-js-plugin/

Still....No error message on UI, but error message is being logged in console.

MaximBalaganskiy commented 8 years ago

@arjyamishra the behavior expects a reporter on a view model behind the control. If you controls are dynamically created then the view model might be different

ma3yta commented 8 years ago

@PWKad @jdanyow When it will be fixed?

jdanyow commented 8 years ago

give the new aurelia-validation and aurelia-validatejs modules a try- this scenario is now supported

http://blog.durandal.io/2016/06/14/new-validation-alpha-is-here/

ma3yta commented 8 years ago

How do it with new validation library https://github.com/aurelia/validatejs/issues/92

ghost commented 7 years ago

Shouts out to @arabsight in Aurelia Gitter.

user = { email: '', password: '' };

    rules = ValidationRules
        .ensure(u => u.email).required().email()
        .ensure(u => u.password).required().minLength(8)
        .rules;

    constructor(controller, authService, aurelia, renderer) {
        this.controller = controller;        
        this.controller.addObject(this.user, this.rules);
    }
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
                        <label class="mdl-textfield__label" for="email">E-Mail</label>
                        <input class="mdl-textfield__input"
                               type="email"
                               id="email" autofocus
                               value.bind="user.email & validate" />
                    </div>

                    <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
                        <label class="mdl-textfield__label" for="password">Password</label>
                        <input class="mdl-textfield__input"
                               type="password"
                               id="password"
                               value.bind="user.password & validate" />
                    </div>