Rodrigo
Rodrigo

Reputation: 3278

Aurelia validating nested objects

I'm trying to validate an object property of an Aurelia ViewModel.

ViewModel

@autoinject
class AddUserForm {
   user: User;
   controller: ValidationController;

    constructor(controllerFactory: ValidationControllerFactory) {
        this.controller = controllerFactory.createForCurrentScope();
    }

    validate() {
        this.controller.validate.then(res => {
            console.log(res.valid);
        })
    }
}

ValidationRules
    .ensure((u: User) => u.id).displayName('User').required()
    .on(AddUserForm)

ViewModel -> View

<template>
    <form click.trigger="validate()">
        <input type="text" value.bind="user.id & validate" />
    </form>
</template>

User

class User {
    id: string
}

The issue I'm having is that the validator is not picking up the nested user object. I'm I missing something to get this working? I read the docs and it seems like this should work. I'm using version ^1.0.0 of the plugin.

Upvotes: 4

Views: 1604

Answers (2)

mgiesa
mgiesa

Reputation: 1013

The problem is in your ValidationRules:

ValidationRules
.ensure((u: User) => u.id).displayName('User').required()
.on(AddUserForm)

needs to be

ValidationRules
.ensure((u: User) => u.id).displayName('User').required()
.on(User)

Then to get the controller to run this rule you either need to include "& validate" somewhere in your value.bind for that property, like this:

<input value.bind="user.id & validate" />

or before you call controller.validate(), add the entire object to the controller like this:

this.controller.addObject(this.user);

I use .addObject all the time because it causes validation to run on properties that aren't included in your markup, and I find I prefer that.

Upvotes: 4

greensponge
greensponge

Reputation: 461

This caused an error when I tried it:

validate() {
    this.controller.validate(res => {
        console.log(res.valid);
    })
}

.validate() expects a ValidateInstruction, in your example you're giving (res: any) => void. I would try changing to this instead:

this.controller.validate().then(res => {
    console.log(res.valid);
});

Leaving .validate() undefined will cause it to validate all objects and bindings, and .then() will execute after that validation has completed. This worked for me when I tried it in my test project.

If I misunderstood your question and this alone does not solve it however, you could also try assigning the User objects id to a property in AddUserForm like this:

public userId = this.user.id;

And changing your ValidationRules and view accordingly:

ViewModel

ValidationRules
    .ensure((u: AddUserForm) => u.userId)
    .displayName("User")
    .required()
    .on(this);

View

<template>
    <form click.delegate="validate()">
        <input type="text" value.bind="userId & validate" />
    </form>
</template>

Upvotes: 0

Related Questions