Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 - Form validation for warnings/hints

I'm trying to add form validations which don't invalidate the form. The validation should only appear as warnings.

E.g. an age validation. An age greater than 90 shows a warning and an age greater than 120 shows an error.

I've tried it with two FormGroups on a form and two [formControl]s on the input field. Only the first [formControl] is used.

Is it possible to use Angulars form validation for this kind of validation? Which approach is the way to go?

like image 429
meleagros Avatar asked Oct 28 '16 15:10

meleagros


2 Answers

I have done it by creating custom validator, which always return null. Also this validator creates additional property warnings. Then just simple check this property from your view.

export interface AbstractControlWarn extends AbstractControl { warnings: any; }

export function tooBigAgeWarning(c: AbstractControlWarn) {
  if (!c.value) { return null; }
  let val = +c.value;
  c.warnings = val > 90 && val <= 120 ? { tooBigAge: {val} } : null;
  return null;
}

export function impossibleAgeValidator(c: AbstractControl) {
  if (tooBigAgeWarning(c) !== null) { return null; }
  let val = +c.value;
  return val > 120 ? { impossibleAge: {val} } : null;
}

@Component({
  selector: 'my-app',
  template: `
    <div [formGroup]="form">
      Age: <input formControlName="age"/>
      <div *ngIf="age.errors?.required" [hidden]="age.pristine">
      Error! Age is required
      </div>
      <div *ngIf="age.errors?.impossibleAge" [hidden]="age.pristine">
      Error! Age is greater then 120
      </div>
      <div *ngIf="age.warnings?.tooBigAge" [hidden]="age.pristine">
      Warning! Age is greater then 90
      </div>
      <p><button type=button [disabled]="!form.valid">Send</button>
    </div>
  `,
})
export class App {
  age: FormControl;
  constructor(private _fb: FormBuilder) { }
  ngOnInit() {
    this.form = this._fb.group({
      age: ['', [
        Validators.required,
        tooBigAgeWarning,
        impossibleAgeValidator]]
    })
    this.age = this.form.get("age");
  }
}

Example: https://plnkr.co/edit/me0pHePkcM5xPQ7nzJwZ?p=preview

like image 127
Sergey Voronezhskiy Avatar answered Oct 22 '22 04:10

Sergey Voronezhskiy


The accepted answer from Sergey Voronezhskiy works perfect in development mode but if you try build in --prod mode you will get this error.

...  Property 'warnings' does not exist on type 'FormControl'.

In order to fix this error I did adjustments to the original code (App class), basically to fix loosely typed variables. This is the new version:

export class FormControlWarn extends FormControl { warnings: any; }

export function tooBigAgeWarning(c: FormControlWarn ) {
    if (!c.value) { return null; }
    let val = +c.value;
    c.warnings = val > 90 && val <= 120 ? { tooBigAge: {val} } : null;
    return null;
}
export function impossibleAgeValidator(c: AbstractControl) {
   if (tooBigAgeWarning(c) !== null) { return null; }
   let val = +c.value;
   return val > 120 ? { impossibleAge: {val} } : null;
}

@Component({
  selector: 'my-app',
  template: `
    <div [formGroup]="form">
      Age: <input formControlName="age"/>
      <div *ngIf="age.errors?.required" [hidden]="age.pristine">
      Error! Age is required
      </div>
      <div *ngIf="age.errors?.impossibleAge" [hidden]="age.pristine">
      Error! Age is greater then 120
      </div>
      <div *ngIf="age.warnings?.tooBigAge" [hidden]="age.pristine">
      Warning! Age is greater then 90
      </div>
      <p><button type=button [disabled]="!form.valid">Send</button>
    </div>
  `,
})
    export class App {
      get age(): FormControlWarn{
         return <FormControlWarn>this.form.get("age");
      }
      constructor(private _fb: FormBuilder) { }
      ngOnInit() {
        this.form = this._fb.group({
          age: new FormControlWarn('', [
            Validators.required,
            tooBigAgeWarning,
            impossibleAgeValidator])
        });       
      }
    }
like image 44
Lazaro Gonzalez Avatar answered Oct 22 '22 05:10

Lazaro Gonzalez