Validation: reduce boilerplate

Hi,
Is it possible to avoid polluting every form-view controller with

this.controller = ctrlFactory.createForCurrentScope();
this.controller.addRenderer(new BootstrapFormRenderer());        

?

My case is an app with significant amount of forms, all of them built with unified styling and structure (Bootstrap)
While I like the Aurelia Validation in general, I dislike boilerplate code.

From the code of ValidationControllerFactory: https://github.com/aurelia/validation/blob/master/src/validation-controller-factory.ts

You can do this:


import { Container } from 'aurelia-framework';
import { ValidationController, Validator, PropertyAccessorParser } from 'aurelia-validation';

/**
 * Creates BootstrapRenderrerValidationControllerFactory  instances.
 */
export class BootstrapRenderrerValidationControllerFactory {
  public static get(container: Container) {
    return new BootstrapRenderrerValidationControllerFactory (container);
  }

  constructor(private container: Container) { }

  /**
   * Creates a new controller instance.
   */
  public create(validator?: Validator) {
    if (!validator) {
      validator = this.container.get(Validator) as Validator;
    }
    const propertyParser = this.container.get(PropertyAccessorParser) as PropertyAccessorParser;
    return new ValidationController(validator, propertyParser);
  }

  /**
   * Creates a new controller and registers it in the current element's container so that it's
   * available to the validate binding behavior and renderers.
   */
  public createForCurrentScope(validator?: Validator) {
    const controller = this.create(validator);
    this.container.registerInstance(ValidationController, controller);
    // add here
    controller.addRenderer(new BootstrapFormRenderer());
    return controller;
  }
}

(BootstrapRenderrerValidationControllerFactory  as any)['protocol:aurelia:resolver'] = true;

Then you can inject and call createForCurrentScope only. Or you can go further and only need to inject your own validation controller that extends ValidationController, and has BootstrapRenderer with it by default:

export class BootstrapValidationController extends ValidationController {
  constructor(validator) {
    super(validator);
    this.addRenderer(new BootstrapFormRenderer());
  }
}

Edit:

There is another way:


import {ValidationControllerFactory } from 'aurelia-validation'

ValidationControllerFactory .prototype.createWithRenderer = function(renderer) {
  let controller = this.createForCurrentScope();
  controller.addRenderer(renderer || new BootstrapFormRenderer());
  return controller;
}

1 Like