DEV Community

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

Posted on

3 2

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

Heroku

Built for developers, by developers.

Whether you're building a simple prototype or a business-critical product, Heroku's fully-managed platform gives you the simplest path to delivering apps quickly — using the tools and languages you already love!

Learn More

Top comments (0)

Playwright CLI Flags Tutorial

5 Playwright CLI Flags That Will Transform Your Testing Workflow

  • 0:56 --last-failed: Zero in on just the tests that failed in your previous run
  • 2:34 --only-changed: Test only the spec files you've modified in git
  • 4:27 --repeat-each: Run tests multiple times to catch flaky behavior before it reaches production
  • 5:15 --forbid-only: Prevent accidental test.only commits from breaking your CI pipeline
  • 5:51 --ui --headed --workers 1: Debug visually with browser windows and sequential test execution

Learn how these powerful command-line options can save you time, strengthen your test suite, and streamline your Playwright testing experience. Click on any timestamp above to jump directly to that section in the tutorial!

Watch Full Video 📹️

👋 Kindness is contagious

Explore a trove of insights in this engaging article, celebrated within our welcoming DEV Community. Developers from every background are invited to join and enhance our shared wisdom.

A genuine "thank you" can truly uplift someone’s day. Feel free to express your gratitude in the comments below!

On DEV, our collective exchange of knowledge lightens the road ahead and strengthens our community bonds. Found something valuable here? A small thank you to the author can make a big difference.

Okay