SimonC
SimonC

Reputation: 385

Aurelia validation inside if.bind and with object property not working

I have a problem with an input validation using the aurelia-validation plugin.

The property bound that I want to validate is a property of an object (that is sometimes null) and it is inside an if.bind on this object.

Here is my code:

<div class="well" if.bind="selectedBody">
    <input type="text" class="input-sm" class="form-control" value.bind="selectedBody.name & validate" required pattern="[a-z]+[aA-zZ|0-9]*">
    <ul if.bind="controller.errors">
        <li repeat.for="error of controller.errors">
             ${error.message}
        </li>
    </ul>
</div>

and my ViewModel constructor:

constructor(private ea : EventAggregator, private controllerFactory: ValidationControllerFactory) {
  this.controller = controllerFactory.createForCurrentScope();
  ValidationRules.ensure('selectedBody.name').required().withMessage("Sprite name is required").on(this);
}

I tried to replace the validation rule by:

ValidationRules.ensure('name').required().withMessage("Sprite name is required").on(this.selectedBody);

but then I need to set my object to an empty object rather than to null and validation doesn't work after the div is hided then shown again.

Upvotes: 0

Views: 912

Answers (2)

MT1
MT1

Reputation: 1

Your self-answered question was helpful to me and I have to post this as an answer because I don't have any StackOverflow points so comment is blocked.

I had run into the same problem you had and was searching for an answer when I found your post. Based on your research, I tried several events and couldn't find anything that only attached the listener once.

I am having a difficult time finding working and complete Aurelia examples so I am posting this to give an alternative. With only about a week of experience using Aurelia and TypeScript this is probably a flawed example but hopefully someone find this useful.

import { inject } from 'aurelia-framework';
import { Tool } from './Tool';
import { ToolingService } from './ToolingService';
import { ValidationControllerFactory, ValidationRules, ValidationController } from 'aurelia-validation';

@inject(ValidationControllerFactory, ToolingService)
export class ToolDetail {
    public tool: Tool;
    public controller: ValidationController;

    constructor(private validationControllerFactory: ValidationControllerFactory, private toolingService: ToolingService) {
        this.controller = validationControllerFactory.createForCurrentScope();
    }

    attachValidation(tool: Tool) {
        ValidationRules.ensure('toolType').required().on(this.tool)
            .ensure('size').required().on(this.tool)
            .ensure('code').required().maxLength(15).on(this.tool)
            .ensure('alternateCode').required().maxLength(15).on(this.tool);

        return tool;
    }

    activate(parms, routeConfig) {
        return this.toolingService.getById(parms.id)
            .then(tool => this.tool = tool)
            .then(tool => { this.attachValidation(this.tool) });
    }
}

That is calling a method like this:

import { HttpClient } from 'aurelia-fetch-client';
import { NewInstance, inject } from 'aurelia-framework';
import { Tool } from './Tool';

@inject(NewInstance.of(HttpClient))
export class ToolingService {

    constructor(private http: HttpClient) {
        http.configure(config => {
            config.useStandardConfiguration()
                .withBaseUrl('/api/Tooling/Tool/');
        });
    }

    getById(id: string): Promise<Tool> {
        return this.http.fetch(id)
            .then(result => result.json() as Promise<Tool>)
            .catch(error => console.log(error));
    }
}

Upvotes: 0

SimonC
SimonC

Reputation: 385

Someone helped me solve my problem on the aurelia gitter (which I highly recommend!)

The solution was to move the validation rule in a property change listener method:

selectedBodyChanged(oldval, newval) {
  if (this.controller.errors) {
    this.controller.reset();
  }
  ValidationRules.ensure('name').required().withMessage("Sprite name is required").on(this.selectedBody);
}

I reset the controller to flush the validation errors displayed by previous selectedBody objects.

Upvotes: 1

Related Questions