Form Validation in Angular Rich Text Editor Component

28 May 202611 minutes to read

The Syncfusion Angular Rich Text Editor supports both template-driven and reactive forms, enabling seamless integration with Angular’s form-building technologies. It supports two-way data binding, validation, and dynamic control for enabling or disabling the editor, making it ideal for capturing and managing rich text content within forms.

Template-Driven Forms

Template-driven forms use Angular directives in the view to handle form controls. To enable template-driven forms, import FormsModule into the corresponding app module.

For more details about template-driven forms, refer to https://angular.io/guide/forms#template-driven-forms.

Add the name attribute to the Rich Text Editor element to identify the form field. To register the Rich Text Editor with ngForm, bind ngModel to it. The FormsModule will then automatically detect the Rich Text Editor as a form element. After that, the Rich Text Editor value will be set based on the ngModel value.

The following example demonstrates two-way data binding with a template-driven form:

import { ButtonModule } from '@syncfusion/ej2-angular-buttons'
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
import { Component, ViewChild } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RichTextEditorAllModule, ToolbarService, LinkService, ImageService, HtmlEditorService, RichTextEditorComponent } from '@syncfusion/ej2-angular-richtexteditor';
@Component({
    imports: [
        RichTextEditorAllModule,
        FormsModule,
        ButtonModule,
        ReactiveFormsModule,
        CommonModule
    ],
    standalone: true,
    selector: 'app-root',
    template: `<div class="control-section">
    <div class="content-wrapper">
        <div id='content' class='box-form' style="margin: 0 auto; max-width:750px; padding:25px">
            <form (ngSubmit)="onSubmit()" #editorForm="ngForm">
                <div class="form-group">
                    <ejs-richtexteditor #fromEditor #name='ngModel' [(value)]='value' required name="name"
                        [(ngModel)]="value" (created)="editorCreated()"></ejs-richtexteditor>
                    <div *ngIf="(name.invalid && name.touched)" class="alert alert-danger">
                        <div *ngIf="name.errors!['required']">
                            Value is required.
                        </div>
                    </div>
                </div>
                <div>
                    <button type="submit" ejs-button [disabled]="!editorForm.valid">Submit</button>
                    <button type="reset" ejs-button style="margin-left: 20px">Reset</button>
                </div>
            </form>
        </div>
    </div>
</div>`,
    providers: [ToolbarService, LinkService, ImageService, HtmlEditorService]
})
export class AppComponent {

    public value: string | null = null;

    @ViewChild('fromEditor')
    private editorEle: RichTextEditorComponent | undefined;

    editorCreated(): void {
        this.editorEle!.element.focus();
    }

    onSubmit(): void {
        alert('Form submitted successfully');
    }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Reactive Forms

Reactive forms use a model-driven technique to handle form data between the component and the view. They listen to form data changes between the App component and the view and also return the validity states and values of form elements.

For more details about Reactive Forms, refer to https://angular.io/guide/reactive-forms.

For reactive forms, import ReactiveFormsModule into the app module. Also, import FormGroup and FormControl into the App component. The FormGroup is used to bind the form using the formGroup directive, and the FormControl is used to bind individual controls using formControlName. When you assign formControlName to the Rich Text Editor, ensure that a corresponding control is created in the FormGroup, and its value will be the default value of the form control.

The following example demonstrates how to bind the Syncfusion Rich Text Editor to an Angular Reactive Form with primitive value binding.

import { CommonModule } from '@angular/common';
import { ButtonModule } from '@syncfusion/ej2-angular-buttons'
import { Component, ViewChild } from '@angular/core';
import { RichTextEditorModule, ToolbarService, LinkService, ImageService, HtmlEditorService, QuickToolbarService, TableService, PasteCleanupService, RichTextEditorComponent } from '@syncfusion/ej2-angular-richtexteditor';
import { FormControl, FormGroup, Validators, AbstractControl, FormsModule, ReactiveFormsModule } from '@angular/forms';
@Component({
    imports: [
        RichTextEditorModule,
        FormsModule,
        CommonModule,
        ButtonModule,
        ReactiveFormsModule
    ],
    standalone: true,
    selector: 'app-root',
    template: `<div class="control-section">
        <div class="content-wrapper">
        <div id="content" class="box-form" style="margin: 0 auto; max-width:750px; padding:25px">
         <form [formGroup]="editorForm">
            <div >
                Rich Text Editor contents:
                <pre></pre>

            </div>
            <div class="example-wrapper">
                <ejs-richtexteditor #fromEditor formControlName="editor" saveInterval=1 >
                </ejs-richtexteditor>
            </div>
        </form>
        </div>
        </div>`,
    providers: [ToolbarService, LinkService, ImageService, HtmlEditorService, QuickToolbarService, TableService, PasteCleanupService]
})
export class AppComponent {

    public editorForm: FormGroup = new FormGroup({
        editor: new FormControl(
          '<p><b>Rich Text Editor</b> with Reactive Form</p>'
        ),
      });
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Disabling the Rich Text Editor Component in Reactive Forms (Angular 15+)

In Angular 15 and later, you can dynamically enable or disable the Syncfusion Rich Text Editor when using Reactive Forms. This is particularly useful when the editor’s availability depends on user actions, form validation states, or other conditions.

Managing the Disabled State

With Angular’s FormControl, you can use the disable() and enable() methods to programmatically control the editor’s availability.

The following example demonstrates how to initialize the Rich Text Editor as a form control and toggle its disabled state dynamically.

import { CommonModule } from '@angular/common';
import { ButtonModule } from '@syncfusion/ej2-angular-buttons'
import { Component } from '@angular/core';
import { RichTextEditorModule, ToolbarService, LinkService, ImageService, HtmlEditorService, QuickToolbarService, PasteCleanupService } from '@syncfusion/ej2-angular-richtexteditor';
import { FormControl, FormGroup, FormsModule, ReactiveFormsModule, FormBuilder } from '@angular/forms';

@Component({
  imports: [
    RichTextEditorModule,
    FormsModule,
    CommonModule,
    ButtonModule,
    ReactiveFormsModule
  ],
  standalone: true,
  selector: 'app-root',
  template: `<div class="control-section">
        <div class="checkbox-wrapper">
            <input type="checkbox" checkBox id="disabled" [(ngModel)]="isDisabled" (change)="onCheckboxChange()"/>
            <label class="checkbox-label" for="disabled">Disabled</label>
        </div>
        <div class="content-wrapper">
        <form [formGroup]="form">
                <ejs-richtexteditor #fromEditor  formControlName="editor" ></ejs-richtexteditor>         
        </form>
        </div>`,
  providers: [ToolbarService, LinkService, ImageService, HtmlEditorService, QuickToolbarService, PasteCleanupService]
})

export class AppComponent {
  public form: FormGroup;
  public isDisabled = true;

  constructor(private formBuilder: FormBuilder) {
    this.form = this.formBuilder.group({
      editor: new FormControl({ value: '', disabled: true }),
    });
  }

  public onCheckboxChange(): void {
    if (this.isDisabled) {
      (this.form as any).get('editor').disable();
      return;
    }
    (this.form as any).get('editor').enable();
  }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));