Last year I built a library to reduce the amount of HTML developers have to write to show validation messages. The library is aimed at Angular's reactive forms and therefore does not help those using template-driven forms. It is also somewhat opinionated, because it moves the declaration of validation messages to the underlying FormGroup model, thus creating lines in your HTML that look like this:

<arv-validation-messages for="age"></arv-validation-messages>

AngularJS' ng-messages

Those of us that worked with AngularJS likely remember the ngMessages directive for displaying validation messages. The relatively clean way of working with it somehow did not make it into Angular thus far. The AngularJS implementation also has some minor downsides. For example, for each field you need to declare when the validation messages are shown. Otherwise they are shown immediately, even if you have never interacted with the control.

The AngularJS documentation describes ngMessages in a rather technical manner:

ngMessages is a directive that is designed to show and hide messages based on the state of a key/value object that it listens on. The directive itself complements error message reporting with the ngModel $error object (which stores a key/value state of validation errors).

The requirements for a better implementation

A better implementation should fit the following requirements:

  • It integrates with reactive and template-driven forms.
  • The interface is simple: pass a control to it, the keys of errors, and the messages you want to display.
  • It is possible to provide a default validation message for cases where the control could have an error without an associated message.
  • The error messages are shown according to some default setting taking into account touched, dirty and form submit state.
  • The default setting can be overridden on a global and control level.

Its usage would be as follows:

import { ValidationMessagesModule } from 'angular-validation-messages';

@NgModule({
  imports: [
    ValidationMessagesModule.forRoot({
      displayValidationMessageWhen: (control, formSubmitted) => {
        return control.dirty && control.touched && formSubmitted;
      }
    });
  ]
})
export class AppModule { }
<!-- the on attribute is only necessary when overriding the configured default behaviour -->
<val-messages for="myControlName" [on]="myControl.touched">
  <val-message for="required">You did not enter text.</val-message>
  <val-message for="minlength">The given text is too short.</val-message>
  <val-message default>An error occurred.</val-message>
</val-messages>

Where to go from here

I have started extracting reusable code from the angular-reactive-validation library into a angular-validation-support library. Afterwards I will start with the implementation of the angular-validation-messages library. More details will follow at a later time.