0
votes

I'm running into problems using Aurelia Validation with dynamically built validation rules. I was successful (but not so elegant) in creating the rules dynamically based on the validation property of an array of form controls, like this:

ctrlAccountSettings = [
  {label: 'Code', type: 'my-textbox', bind: 'acc_code', validation: '.required().minLength(17).maxLength(30)'},
  {label: 'Name_orig', type: 'my-textbox', bind: 'acc_name_orig', validation: '.required().minLength(3).maxLength(100)'},
  {label: 'Name_tran', type: 'my-textbox', bind: 'acc_name_tran', validation: '.minLength(3).maxLength(100)'},
  {label: 'Description', type: 'my-textarea', rows: '3', bind: 'acc_description', validation: '.maxLength(255)'},
  {label: 'Status', type: 'my-dropdown', bind: 'acc_status', enum: 'ActiveInactive', validation: '.required()'}];

And this code to create/apply the rules in my view-model:

attached() {
  // define rules based on controls
  this.rules = [];
  this.controls.map(control => {
    if (control.validation) {
      if (control.validation.match(/\.required\(\)/)) { this.rules.push(ValidationRules.ensure(control.bind).required().rules[0]); }
      let minLength = control.validation.match(/\.minLength\(([0-9]+)\)/);
      if (minLength) { this.rules.push(ValidationRules.ensure(control.bind).minLength(minLength[1]).rules[0]); }
      let maxLength = control.validation.match(/\.maxLength\(([0-9]+)\)/);
      if (maxLength) { this.rules.push(ValidationRules.ensure(control.bind).maxLength(maxLength[1]).rules[0]); }
    }
  });
  // initialize modelEdit and add validation rules
  this.modelEdit = {};
  // this.validationCtrl.removeAllObjects();            doesn't exist
  // this.validationCtrl.removeObject(this.modelEdit);  doesn't work
  // this.validationCtrl.destroy();                     not sure how to recover from this
  this.validationCtrl.addObject(this.modelEdit, this.rules);
}

The problem is that as this same component is re-attached several times, I get duplicate rules lingering that prevent the form from being validated.

Question 1 (most important): How do I use removeObject() or a similar method to clean up previous validation?

Question 2: Is there a better way to apply the validation rules from my array of control objects dynamically? I don't like having to create a this.rules.push() option for every type of rule.

Question 3: My controls aren't changing. Is there a better way to keep the rules in place even when the object is swapped out?

1
Here's a gist you can use to create a reproduction of your issue: gist.run/?id=381fdb1a4b0865a4c25026187db865ceJeremy Danyow
Thanks. Here's an approximation of what I'm trying to do. It looks like the main problem I was experiencing is corrected by adding a controller.reset() before swapping the entity. But that doesn't answer questions 2 and 3. Any ideas or suggestions looking at my code? gist.run/?id=22f17210934d436e231b223b235fcd32LStarky

1 Answers

2
votes

Answer to question 1

When you call controller.validate() with no args, the controller will validate all objects you've given it via addObject. Based on the UI in your gist, it seems like you need to call removeObject to remove the previously added object before adding a new object instance in your goCreate or goEdit methods. Here's an example. Without calling removeObject (or reset) the controller thinks it still needs to validate the previously added object(s).

Answer to question 2

We're looking at ways to improve the process for adding creating rules from data. Here's an alternative approach: https://github.com/aurelia/validation/issues/363

Here's the issue for enhancing the API for this: https://github.com/aurelia/validation/issues/400

Answer to question 3

Your gist makes the association between the object and it's rules by passing both the object and the rules to controller.addObject. That's the best way to do it when you're using addObject. That said, you probably don't need to use addObject. Your code might be simpler if you remove the addObject / reset code and specify the rules in your bindings like this. This will cause the controller to use the default behavior which only validates objects+properties currently used in & validate bindings.