DEV Community

Cover image for Intuitive Decorators of RxWeb for Angular Reactive Forms
Ushmi Dave
Ushmi Dave

Posted on

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;
}
Enter fullscreen mode Exit fullscreen mode


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);
    }
}
Enter fullscreen mode Exit fullscreen mode


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>
Enter fullscreen mode Exit fullscreen mode

@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;
}
Enter fullscreen mode Exit fullscreen mode


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);
    }
}
Enter fullscreen mode Exit fullscreen mode


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>
Enter fullscreen mode Exit fullscreen mode

@ 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;

}
Enter fullscreen mode Exit fullscreen mode


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");

    }
}
Enter fullscreen mode Exit fullscreen mode


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>
Enter fullscreen mode Exit fullscreen mode

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

Top comments (0)