Codementor Events

Intuitive Decorators of RxWeb for Angular Reactive Forms

Published Aug 14, 2020
Intuitive Decorators of RxWeb for Angular Reactive Forms

In this article, we discuss rxweb decorators, which help us to reduce the HTML template code and make our code more readable; likewise:

  1. Show error messages conditionally.
  2. Disabling FormControl conditionally without subscribing any FormControl ValueChanges,
  3. Conditionally assign a class on the element.

If you are unaware about the decorator-based validation in reactive forms using RxWeb, then I would suggest referring to this good article Decorator based reactive forms in Angular — An efficient way to validate forms

Import the decorator after Installing @rxweb/reactive-form-validators, after installing import RxReactiveFormsModule in the main module of the angular project

@disable

We come accross a lot of cases where we need to disable a control conditionally, In other words disable a control based upon other input's value. In this case the field of License Number becomes abled only when the age is greater than equal to 18

Stackblitz Example : Open

decorator-article.gif

This is achieved using the following steps

1) user.model.ts:

import { disable, prop } from "@rxweb/reactive-form-validators";
import { AbstractControl } from "@angular/forms";

export class User {
  @prop()
  age: number;

  @disable({
    conditionalExpression: function(control: AbstractControl) {
      return this.age <= 18 ? true : false;
    }
  }) 
  @prop()
  licenseNumber: string;
}

2) user.component.ts:

import { Component, OnInit } from '@angular/core';
import { FormGroup } from "@angular/forms";

import { RxFormBuilder } from '@rxweb/reactive-form-validators';
import { User } from './user.model';

@Component({
    selector: 'app-user-add',
    templateUrl: './user-add.component.html'
})

export class UserAddComponent implements OnInit {
    userFormGroup: FormGroup;
    constructor(private formBuilder: RxFormBuilder) { }

    ngOnInit() {
        let user = new User();
        this.userFormGroup = this.formBuilder.formGroup(user);
    }
}

3) user.component.html:

<form *ngIf="userFormGroup" [formGroup]="userFormGroup">
  <div class="form-group">
    <label>Age</label>
    <input type="text" formControlName="age" class="form-control"  />
    </div>
  <div class="form-group">
      <label>License Number</label>
      <input type="text" formControlName="licenseNumber" class="form-    control"  />
    </div>
</form>

@elementClass

Setting css class based upon some condition into a formControl. In this case the invalid class is applied when the state is touched or dirty and has errors

decorator-article1.gif

Stackblitz Example : Open

1) user.model.ts:

import {  prop,elementClass,alpha } from "@rxweb/reactive-form-validators"
import { AbstractControl } from "@angular/forms"

export class User {


   @elementClass({
       conditionalExpression: function (control:AbstractControl) {
           return (control.touched || control.dirty) && control.errors ? 'has- error' : '';
       }})
   @alpha()
   userName: string;
}

2) user.component.ts:

import { Component, OnInit } from '@angular/core';
import { FormGroup } from "@angular/forms";

import { RxFormBuilder } from '@rxweb/reactive-form-validators';
import { User } from './user.model';

@Component({
    selector: 'app-user-add',
    templateUrl: './user-add.component.html'
})

export class UserAddComponent implements OnInit {
    userFormGroup: FormGroup;
    constructor(private formBuilder: RxFormBuilder) { }

    ngOnInit() {
        let user = new User();
        this.userFormGroup = this.formBuilder.formGroup(user);
    }
}

3) user.component.html:

<form *ngIf="userFormGroup" [formGroup]="userFormGroup">
    <div class="form-group">
      <label>User Name</label>
      <input type="text" formControlName="userName" class="form-control"  />
    </div>  
</form>

@error

This decorator is used to display error based upon some condition. In this case the error messages are displayed when the submit button is clicked

Stackblitz Example : Open

decorator-article2.gif

1) form.model.ts:

import { required,error,prop } from "@rxweb/reactive-form-validators"
import {AbstractControl } from "@angular/forms"
export class FormField{
  
  @prop()
  action:string;

  @error({conditionalExpression:function(control:AbstractControl){ return this.action === "submit"}})
  @required()
  firstName:string;

  @error({conditionalExpression:function(control:AbstractControl){ return this.action == "submit"}})
  @required()
  userName:string;
 
}

2) user.component.ts:

import { Component, OnInit } from '@angular/core';
import { FormGroup,Validators } from "@angular/forms"

import { RxFormGroup,FormGroupExtension,RxFormBuilder,FormBuilderConfiguration,RxwebValidators } from '@rxweb/reactive-form-validators';
import { FormField } from './form.model';


@Component({
    selector: 'app-user-add',
    templateUrl: './user-add.component.html'
})
export class UserAddComponent implements OnInit {
    errorObject = {}
    userInfoFormGroup: FormGroup

    constructor(
        private formBuilder: RxFormBuilder
    ) { }

    ngOnInit() {
      var formField = new FormField();
        this.userInfoFormGroup =<RxFormGroup>this.formBuilder.formGroup(formField);
    }

    submit(){
      if(this.userInfoFormGroup.invalid)
        this.userInfoFormGroup.controls.action.setValue("submit");
      
    }
}

3) user.component.html:

<form [formGroup]="userInfoFormGroup">
  <div class="form-group">
    <label>First Name</label>
    <input type="text" formControlName="firstName" class="form-control"  />
    <small class="form-text text-danger" >{{userInfoFormGroup.controls.firstName["errorMessage"]}}</small>
  </div>
  <div class="form-group">
    <label>User Name</label>
    <input type="text" formControlName="userName" class="form-control"  />
    <small class="form-text text-danger" >{{userInfoFormGroup.controls.userName["errorMessage"]}}</small>
  </div>
  <button (click)="submit()" class="btn btn-primary">Submit</button>
</form>

Conclusion

This article show some of the best and most used cases which is fulfiled in the most intuitive and elegant way using model based approach, To know more about other useful decorators refer documentation section

Discover and read more posts from Ushmi Dave
get started