Add reactive forms within a tab in Angular Tab component
22 Sep 202524 minutes to read
The Tab component supports rendering other components inside tab panels using Angular ng-template. This includes integrating reactive forms within individual tab items to create organized, multi-section form interfaces.
For more details about Reactive Forms refer: https://angular.io/guide/reactive-forms.
To implement reactive forms within tabs, import the ReactiveFormsModule into the app module. Additionally, import FormGroup and FormControl into the app component. The FormGroup declares the formGroupName for the entire form, while FormControl declares individual formControlName properties for specific form controls. Each FormControl can be applied to form elements like AutoComplete as standard practice. Create a value object for the FormGroup where each property represents the default value for its corresponding form control.
After creating the reactive form structure, reference it directly within the ng-template to render the form content inside the tab panel.
The following example demonstrates how to add reactive forms within a Tab item using ng-template.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
import { TabModule } from '@syncfusion/ej2-angular-navigations'
import { AutoCompleteModule } from '@syncfusion/ej2-angular-dropdowns'
import { DropDownListModule } from '@syncfusion/ej2-angular-dropdowns'
import { ButtonModule } from '@syncfusion/ej2-angular-buttons'
import { Component, Inject } from '@angular/core';
import { FormBuilder, FormsModule, FormGroup, Validators } from '@angular/forms';
@Component({
imports: [ FormsModule, ReactiveFormsModule, AutoCompleteModule, DropDownListModule, ButtonModule,TabModule ],
standalone: true,
selector: 'app-container',
template: `
<ejs-tab id="element" #tab>
<e-tabitems>
<e-tabitem [header]='headerText[0]'>
<ng-template #content>
<div id="reactive-form">
<div class="control-section">
<div class="col-lg-8 content-wrapper">
<div id='content' class='box-form' style="margin: 0 auto; width:250px; padding:25px">
<form [formGroup]="skillForm" novalidate id="formId">
<div class="form-group">
<ejs-autocomplete formControlName="skillname" name="skillname"
[dataSource]='skillset' allowCustom=false [placeholder]='placeholder'
floatLabelType='Auto'>
</ejs-autocomplete>
</div>
<div class="form-group" style="padding-top:10px;">
<div class="e-float-input">
<input type="text" autocomplete="off" (focus)="onfocus($event)"
(blur)="onblur($event)" formControlName="sname" name="sname"
maxlength="10" />
<span class="e-float-line"></span>
<label class="e-float-text e-label-bottom">Name:</label>
</div>
</div>
<div class="form-group" style="padding-top:10px;">
<div class="e-float-input">
<input type="text" autocomplete="off" (focus)="onfocus($event)"
(blur)="onblur($event)" formControlName="smail" maxlength="15" />
<span class="e-float-line"></span>
<label class="e-float-text e-label-bottom">Email:</label>
</div>
</div>
<div class="form-group" style="padding:10px;">
<div class="col-xs-6 col-sm-6 col-lg-6 col-md-6">
<button ejs-button [disabled]="!skillForm.valid">Done</button></div>
<div class="col-xs-6 col-sm-6 col-lg-6 col-md-6">
<button ejs-button type="reset" (click)="onreset($event)">Cancel</button>
</div>
</div>
</form>
</div>
</div>
<div class="col-lg-4 property-section">
<div class="property-panel-section">
<div class="property-panel-header">Properties</div>
<div class="property-panel-content" style="padding: 10px;">
<table id="property" class="box-table" title="Properties" style="width: 100%;">
<tr>
<td style="width:50%">Selected Language: </td>
<td class="formtext"></td>
</tr>
<tr>
<td style="width:50%">Buyer Name: </td>
<td class="formtext"></td>
</tr>
<tr>
<td style="width:50%">Buyer Mail ID: </td>
<td class="formtext"></td>
</tr>
</table>
</div>
</div>
</div>
</div>
</div>
</ng-template>
</e-tabitem>
<e-tabitem [header]='headerText[1]'>
<ng-template #content>
<div class="row" style="width:500px;">
<div class="col-xs-7 col-sm-7 col-lg-7 col-md-7" style="padding-top:20px;">
<div style="webkit-box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), 0 3px 1px -2px rgba(0,0,0,0.12), 0 1px 5px 0 rgba(0,0,0,0.2);
box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), 0 3px 1px -2px rgba(0,0,0,0.12), 0 1px 5px 0 rgba(0,0,0,0.2);
margin:0 auto;height:330px;">
<div style="padding:30px;">
<form #form="ngForm">
<div class="form-group">
<ejs-dropdownlist name="skillname" [(ngModel)]='skillForm.skillname'
[dataSource]='skillset' [placeholder]='placeholder' floatLabelType='Auto'>
</ejs-dropdownlist>
</div>
<div class="form-group" style="padding-top:10px;">
<div class="e-float-input">
<input type="text" [(ngModel)]="skillForm.sname" name="sname"
maxlength="10" />
<span class="e-float-line e-label-top"></span>
<label class="e-float-text e-label-top">Name:</label>
</div>
</div>
<div class="form-group" style="padding-top:10px;">
<div class="e-float-input">
<input type="text" [(ngModel)]="skillForm.smail" name="smail"
maxlength="15" />
<span class="e-float-line e-label-top"></span>
<label class="e-float-text e-label-top">Email:</label>
</div>
</div>
<div class="form-group" style="padding:10px;">
<button ejs-button>Done</button>
<button ejs-button type="reset">Cancel</button>
</div>
</form>
</div>
</div>
</div>
<div class="col-xs-5 col-sm-5 col-lg-5 col-md-5" style="padding-top:20px;">
<div style="webkit-box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), 0 3px 1px -2px rgba(0,0,0,0.12), 0 1px 5px 0 rgba(0,0,0,0.2);
box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), 0 3px 1px -2px rgba(0,0,0,0.12), 0 1px 5px 0 rgba(0,0,0,0.2);
margin:0 auto;height:330px;">
<div style="padding:30px;">
<div class="form-group">
<span style="font-weight:800;">Selected Language: </span>
<span style="font-style:oblique;color:#8a2be2;">
</span>
</div>
<div class="form-group" style="padding-top:50px;">
<span style="font-weight:800;">Buyer Name: </span>
<span style="font-style:oblique;color:#8a2be2;">
</span>
</div>
<div class="form-group" style="padding-top:50px;">
<span style="font-weight:800;">Buyer Mail ID: </span>
<span style="font-style:oblique;color:#8a2be2;">
</span>
</div>
</div>
</div>
</div>
</div>
</ng-template>
</e-tabitem>
</e-tabitems>
</ejs-tab>
`
})
export class AppComponent {
public headerText: Object | any = [{ 'text': 'ReactiveForms1' }, { 'text': 'ReactiveForms2' }];
public skillset: string[] = [
'ASP.NET', 'ActionScript', 'Basic',
'C++', 'C#', 'dBase', 'Delphi',
'ESPOL', 'F#', 'FoxPro', 'Java',
'J#', 'Lisp', 'Logo', 'PHP'
];
public placeholder: String = 'Select a language';
public skillForm!: FormGroup;
constructor(@Inject(FormBuilder) private builder: FormBuilder) {
this.createForm();
}
createForm(): void {
this.skillForm = this.builder.group({
skillname: ['', Validators.required],
sname: ['', Validators.required],
smail: ['', Validators.required]
});
}
onfocus(element: FocusEvent): void {
let target: HTMLInputElement = element.target as HTMLInputElement;
let parentNode: HTMLElement = target.parentNode as HTMLElement;
if (parentNode.classList.contains('e-input-in-wrap')) {
parentNode = (parentNode.parentNode as HTMLElement);
}
parentNode.classList.add('e-input-focus');
(parentNode.children[2] as Element).classList.add('e-label-top');
(parentNode.children[2] as Element).classList.remove('e-label-bottom');
}
onblur(element: FocusEvent): void {
let target: HTMLInputElement = element.target as HTMLInputElement;
let parentNode: HTMLElement = target.parentNode as HTMLElement;
if (parentNode.classList.contains('e-input-in-wrap')) {
(parentNode.parentNode as HTMLElement).classList.remove('e-input-focus');
}
parentNode.classList.remove('e-input-focus');
if (target.value === null || target.value === '') {
(parentNode.children[2] as Element).classList.remove('e-label-top');
(parentNode.children[2] as Element).classList.add('e-label-bottom');
} else {
(parentNode.children[2] as Element).classList.add('e-label-top');
(parentNode.children[2] as Element).classList.remove('e-label-bottom');
}
}
onreset(element: MouseEvent): void {
let parentNode: NodeListOf<HTMLElement> = document.getElementsByClassName('box-form')[0].querySelectorAll('.e-float-text');
for (let i: number = 0; i < parentNode.length; i++) {
parentNode[i].classList.remove('e-label-top');
parentNode[i].classList.add('e-label-bottom');
}
}
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));