How can I help you?
Template Editing in Angular Grid Component
10 Mar 202624 minutes to read
The Syncfusion® Angular Grid component supports template editing, providing a powerful and flexible way to customize the appearance and behavior of cells during editing. Angular templates enable defining the structure and content of cells within the grid.
For grid basic editing setup and configuration, refer to the Edit Feature Setup.
Inline or dialog template editing
The Syncfusion Grid provides support for inline and dialog template editing, enabling customization of the editing experience using either Reactive or Template-driven Forms. These forms can be used to add and update grid records.
To enable this feature, set the editSettings.mode property to either Normal or Dialog and define grid editors using the editSettings.template template variable of ngTemplate.
Using Reactive Forms
Reactive forms take a programmatic, model-driven approach to handling forms with TypeScript, offering dynamic control over form structure, state management, validation, and error handling. This is ideal for scenarios requiring custom logic or the inclusion of editors for fields that are not part of the grid column model. Dialog templates allow for additional editors beyond the default edit dialog.
In this example, a FormGroup with relevant FormControls is created during the actionBegin event. When saving, the form is validated, and, if successful, the grid updates using the data from the FormGroup.
import { CommonModule } from '@angular/common';
import { GridModule, EditService, ToolbarService, PageService } from '@syncfusion/ej2-angular-grids'
import { ReactiveFormsModule, FormsModule } from '@angular/forms'
import { NumericTextBoxAllModule } from '@syncfusion/ej2-angular-inputs'
import { DatePickerAllModule } from '@syncfusion/ej2-angular-calendars';
import { DropDownListAllModule } from '@syncfusion/ej2-angular-dropdowns';
import {TextAreaModule} from '@syncfusion/ej2-angular-inputs';
import { Component, OnInit } from '@angular/core';
import { orderDetails } from './datasource';
import { DialogEditEventArgs, SaveEventArgs } from '@syncfusion/ej2-angular-grids';
import { DataUtil } from '@syncfusion/ej2-data';
import { FormGroup, AbstractControl, FormControl, Validators } from '@angular/forms';
@Component({
imports: [
GridModule,
NumericTextBoxAllModule, DatePickerAllModule,CommonModule,
DropDownListAllModule, ReactiveFormsModule, FormsModule,TextAreaModule
],
providers: [EditService, ToolbarService, PageService],
standalone: true,
selector: 'app-root',
templateUrl: `reactive-form.html`
})
export class AppComponent implements OnInit {
public data?: Object[];
public editSettings?: Object;
public toolbar?: string[];
public orderForm?: FormGroup|any;
public pageSettings?: Object;
public shipCityDistinctData?: Object[];
public shipCountryDistinctData?: Object[];
public submitClicked: boolean = false;
public ngOnInit(): void {
this.data = orderDetails;
this.editSettings = { allowEditing: true, allowAdding: true, allowDeleting: true, mode: 'Dialog' };
this.toolbar = ['Add', 'Edit', 'Delete'];
this.pageSettings = { pageCount: 5};
this.shipCityDistinctData = DataUtil.distinct(orderDetails, 'ShipCity', true);
this.shipCountryDistinctData = DataUtil.distinct(orderDetails, 'ShipCountry', true );
}
createFormGroup(data: IOrderModel): FormGroup {
return new FormGroup({
OrderID: new FormControl(data.OrderID, Validators.required),
OrderDate: new FormControl(data.OrderDate, (this.dateValidator() as Object)),
CustomerName: new FormControl(data.CustomerName, Validators.required),
Freight: new FormControl(data.Freight,Validators.required),
ShipAddress: new FormControl(data.ShipAddress,Validators.required),
ShipCity: new FormControl(data.ShipCity,Validators.required),
ShipCountry: new FormControl(data.ShipCountry,Validators.required)
});
}
dateValidator() {
return (control: FormControl): null | Object => {
return control.value && control.value.getFullYear &&
(1900 <= control.value.getFullYear() && control.value.getFullYear() <= 2099) ? null : { OrderDate: { value : control.value}};
}
}
actionBegin(args: SaveEventArgs): void {
if (args.requestType === 'beginEdit' || args.requestType === 'add') {
this.submitClicked = false;
this.orderForm = this.createFormGroup((args.rowData as Object));
}
if (args.requestType === 'save') {
this.submitClicked = true;
if (this.orderForm.valid) {
args.data = this.orderForm.value;
} else {
args.cancel = true;
}
}
}
actionComplete(args: DialogEditEventArgs): void {
if ((args.requestType === 'beginEdit' || args.requestType === 'add')) {
// Set initial focus
if (args.requestType === 'beginEdit') {
((args.form as HTMLFormElement).elements.namedItem('CustomerName') as HTMLInputElement).focus();
} else if (args.requestType === 'add') {
((args.form as HTMLFormElement).elements.namedItem('OrderID') as HTMLInputElement).focus();
}
}
}
get OrderID(): AbstractControl { return this.orderForm.get('OrderID'); }
get CustomerName(): AbstractControl { return this.orderForm.get('CustomerName'); }
get OrderDate(): AbstractControl { return this.orderForm.get('OrderDate'); }
get Freight(): AbstractControl { return this.orderForm.get('Freight'); }
get ShipCountry(): AbstractControl { return this.orderForm.get('ShipCountry'); }
get ShipCity(): AbstractControl { return this.orderForm.get('ShipCity'); }
}
export interface IOrderModel {
OrderID?: number;
CustomerName?: string;
ShipCity?: string;
OrderDate?: Date;
Freight?: number;
ShipCountry?: string;
ShipAddress?: string;
}<div class="control-section">
<ejs-grid [dataSource]='data' height="275px" allowPaging='true' [pageSettings]='pageSettings' [editSettings]='editSettings'
[toolbar]='toolbar' (actionBegin)='actionBegin($event)' (actionComplete)='actionComplete($event)'>
<e-columns>
<e-column field='OrderID' headerText='Order ID' width='120' textAlign='Right'
[isPrimaryKey]='true'></e-column>
<e-column field='CustomerName' headerText='Customer Name' width='120'></e-column>
<e-column field='Freight' headerText='Freight' width='120' format='C2' textAlign='Right'></e-column>
<e-column field='OrderDate' headerText='Order Date' width='130' format='yMd' textAlign='Right'></e-column>
<e-column field='ShipCountry' headerText='Ship Country' width='150'></e-column>
</e-columns>
<ng-template #editSettingsTemplate let-data>
<div [formGroup]="orderForm">
<div class="form-row">
<div class="form-group col-md-6">
<div class="e-float-input e-control-wrapper"
[ngClass]="{'e-error': OrderID.invalid && (OrderID.dirty || OrderID.touched)}">
<input formControlName="OrderID" data-msg-containerid='OrderIDError' id="OrderID"
name="OrderID" type="text" [attr.disabled]="!data.isAdd ? '' : null">
<span class="e-float-line"></span>
<label class="e-float-text e-label-top" for="OrderID"> Order ID</label>
</div>
<div id="OrderIDError"
[style.visibility]='((OrderID.invalid && (OrderID.dirty || OrderID.touched)) || (OrderID.invalid && submitClicked))? "visible": "hidden"'>
<label class="e-error" for="OrderID" id="OrderID-info" style="display: block;">*Order ID is
required</label>
</div>
</div>
<div class="form-group col-md-6">
<div class="e-float-input e-control-wrapper"
[ngClass]="{'e-error': CustomerName.invalid && (CustomerName.dirty || CustomerName.touched)}">
<input formControlName="CustomerName" data-msg-containerid='CustomerNameError'
id="CustomerName" name="CustomerName" type="text">
<span class="e-float-line"></span>
<label class="e-float-text e-label-top" for="CustomerName">Customer Name</label>
</div>
<div id="CustomerNameError"
[style.visibility]='((CustomerName.invalid && (CustomerName.dirty || CustomerName.touched)) || (CustomerName.invalid && submitClicked))? "visible": "hidden"'>
<label class="e-error" for="CustomerName" id="CustomerName-info"
style="display: block;">*Customer Name is required</label>
</div>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<ejs-numerictextbox formControlName="Freight" id="Freight" placeholder="Freight"
floatLabelType='Always'></ejs-numerictextbox>
<div id="FreightError"
[style.visibility]='((Freight.invalid && (Freight.dirty || Freight.touched)) || (Freight.invalid && submitClicked)) ? "visible": "hidden"'>
<label class="e-error" for="Freight" id="Freight-info" style="display: block;">*Order Date
is required</label>
</div>
</div>
<div class="form-group col-md-6">
<ejs-datepicker id="OrderDate" formControlName="OrderDate" placeholder="Order Date"
floatLabelType='Always'></ejs-datepicker>
<div id="OrderDateError"
[style.visibility]='((OrderDate.invalid && (OrderDate.dirty || OrderDate.touched)) || (OrderDate.invalid && submitClicked)) ? "visible": "hidden"'>
<label class="e-error" for="OrderDate" id="OrderDate-info" style="display: block;">*Order
Date is required</label>
</div>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<ejs-dropdownlist id="ShipCountry" formControlName="ShipCountry"
[dataSource]='shipCountryDistinctData'
[fields]="{text: 'ShipCountry', value: 'ShipCountry' }" placeholder="Ship Country"
popupHeight='300px' floatLabelType='Always'></ejs-dropdownlist>
<div id="ShipCountryError"
[style.visibility]='((ShipCountry.invalid && (ShipCountry.dirty || ShipCountry.touched)) || (ShipCountry.invalid && submitClicked)) ? "visible": "hidden"'>
<label class="e-error" for="ShipCountry" id="ShipCountry-info" style="display: block;">*Ship
Country is required</label>
</div>
</div>
<div class="form-group col-md-6">
<ejs-dropdownlist id="ShipCity" formControlName="ShipCity" [dataSource]='shipCityDistinctData'
[fields]="{text: 'ShipCity', value: 'ShipCity' }" placeholder="Ship City"
popupHeight='300px' floatLabelType='Always'></ejs-dropdownlist>
<div id="ShipCityError"
[style.visibility]='((ShipCity.invalid && (ShipCity.dirty || ShipCity.touched)) || (ShipCity.invalid && submitClicked)) ? "visible": "hidden"'>
<label class="e-error" for="ShipCity" id="ShipCity-info" style="display: block;">*Ship City
is required</label>
</div>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-12">
<div class="e-float-input e-control-wrapper">
<textarea formControlName="ShipAddress" id="ShipAddress" name="ShipAddress"
type="text"></textarea>
<span class="e-float-line"></span>
<label class="e-float-text e-label-top" for="ShipAddress">Ship Address</label>
</div>
</div>
</div>
</div>
</ng-template>
</ejs-grid>
</div>import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));Using Template-driven Forms
Template-driven forms use HTML with Angular’s two-way data binding and the ngModel directive, making syntax simple and code minimal. This method is best for straightforward forms with simple validation requirements.
In the following example, a FormGroup is created using the ngForm directive. During the save operation, the form group is validated, and the grid is updated with the edited model data.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { CommonModule } from '@angular/common';
import { GridModule, EditService, ToolbarService } from '@syncfusion/ej2-angular-grids'
import { ReactiveFormsModule, FormsModule } from '@angular/forms'
import { NumericTextBoxAllModule } from '@syncfusion/ej2-angular-inputs'
import { DatePickerAllModule } from '@syncfusion/ej2-angular-calendars'
import { DropDownListAllModule } from '@syncfusion/ej2-angular-dropdowns'
import { Component, OnInit, ViewChild } from '@angular/core';
import { data } from './datasource';
import { DialogEditEventArgs, SaveEventArgs} from '@syncfusion/ej2-angular-grids';
import { DataUtil } from '@syncfusion/ej2-data';
import { FormGroup } from '@angular/forms';
@Component({
imports: [
GridModule,
NumericTextBoxAllModule, DatePickerAllModule, DropDownListAllModule,ReactiveFormsModule, FormsModule,CommonModule
],
providers: [EditService, ToolbarService],
standalone: true,
selector: 'app-root',
templateUrl: `template-driven.html`
})
export class AppComponent implements OnInit {
public data?: Object[];
public editSettings?: Object;
public toolbar?: string[];
public pageSettings?: Object;
public shipCityDistinctData?: Object[];
public shipCountryDistinctData?: Object[];
public orderData!: IOrderModel;
@ViewChild('orderForm') public orderForm?: FormGroup|any;
public ngOnInit(): void {
this.data = data;
this.editSettings = { allowEditing: true, allowAdding: true, allowDeleting: true, mode: 'Normal' };
this.toolbar = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];
this.pageSettings = { pageCount: 5};
this.shipCityDistinctData = DataUtil.distinct(data, 'ShipCity', true);
this.shipCountryDistinctData = DataUtil.distinct(data, 'ShipCountry', true );
}
actionBegin(args: SaveEventArgs): void {
if (args.requestType === 'beginEdit' || args.requestType === 'add') {
this.orderData = Object.assign({}, args.rowData);
}
if (args.requestType === 'save') {
if (this.orderForm.valid) {
args.data = this.orderData;
} else {
args.cancel = true;
}
}
}
actionComplete(args: DialogEditEventArgs): void {
if (args.requestType === 'beginEdit' || args.requestType === 'add') {
// Set initial focus
if (args.requestType === 'beginEdit') {
((args.form as HTMLFormElement).elements.namedItem('CustomerName') as HTMLInputElement).focus();
} else if (args.requestType === 'add') {
((args.form as HTMLFormElement).elements.namedItem('OrderID') as HTMLInputElement).focus();
}
}
}
public focusIn(event: FocusEvent): void {
((event.target as HTMLElement).parentElement as HTMLElement).classList.add('e-input-focus');
}
public focusOut(event: FocusEvent): void {
((event.target as HTMLElement).parentElement as HTMLElement).classList.remove('e-input-focus');
}
}
export interface IOrderModel {
OrderID?: number;
CustomerName?: string;
ShipCity?: string;
OrderDate?: Date;
Freight?: number;
ShipCountry?: string;
ShipAddress?: string;
}<div class="control-section">
<ejs-grid [dataSource]='data' height="280px" allowPaging='true' [pageSettings]='pageSettings' [editSettings]='editSettings'
[toolbar]='toolbar' (actionBegin)='actionBegin($event)' (actionComplete)='actionComplete($event)'>
<e-columns>
<e-column field='OrderID' headerText='Order ID' width='120' textAlign='Right'
[isPrimaryKey]='true'></e-column>
<e-column field='CustomerName' headerText='Customer Name' width='120'></e-column>
<e-column field='Freight' headerText='Freight' width='120' format='C2' textAlign='Right'></e-column>
<e-column field='OrderDate' headerText='Order Date' width='130' format='yMd' textAlign='Right'></e-column>
<e-column field='ShipCountry' headerText='Ship Country' width='150'></e-column>
</e-columns>
<ng-template #editSettingsTemplate let-data>
<div ngForm #orderForm="ngForm">
<table class="e-table e-inline-edit" cellspacing="0.25">
<colgroup>
<col style="width: 120px;">
<col style="width: 120px;">
<col style="width: 120px;">
<col style="width: 130px;">
<col style="width: 150px;">
</colgroup>
<tbody>
<tr>
<td style="text-align: right" class='e-rowcell'>
<div class="e-input-group" [ngClass]="{'e-disabled': !data.isAdd}">
<input class="e-input e-field" [(ngModel)]="orderData.OrderID" required
[attr.disabled]="!data.isAdd ? '' : null" name='OrderID' type="text"
(focus)="focusIn($event)" (blur)="focusOut($event)" style="text-align: right"
#OrderID="ngModel" />
</div>
</td>
<td class='e-rowcell'>
<div class="e-input-group">
<input class="e-input e-field" name='CustomerName'
[(ngModel)]="orderData.CustomerName" required type="text"
(focus)="focusIn($event)" (blur)="focusOut($event)" #CustomerName="ngModel" />
</div>
</td>
<td style="text-align: right" class='e-rowcell'>
<ejs-numerictextbox name="Freight" id="Freight" [(ngModel)]="orderData.Freight"
floatLabelType='Never'></ejs-numerictextbox>
</td>
<td style="text-align: right" class='e-rowcell'>
<ejs-datepicker id="OrderDate" name="OrderDate" [(ngModel)]="orderData.OrderDate"
floatLabelType='Never'></ejs-datepicker>
</td>
<td class='e-rowcell'>
<ejs-dropdownlist id="ShipCountry" name="ShipCountry"
[(ngModel)]="orderData.ShipCountry" [dataSource]='shipCountryDistinctData'
[fields]="{text: 'ShipCountry', value: 'ShipCountry' }" popupHeight='300px'
floatLabelType='Never'></ejs-dropdownlist>
</td>
</tr>
</tbody>
</table>
</div>
</ng-template>
</ejs-grid>
</div>import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));Each form field must have a
nameattribute.
Using template context
Enhance custom edit forms by accessing the template context: obtain row details, render editors as components, retrieve values from editors, set the initial focus, disable default validation, and add custom validation. These features work for both inline and dialog modes.
The below scenarios are demonstrated in detail with tab component inside the dialog template.
Access row details inside ngTemplate using template context
Edit templates provide access to crucial row information within an ngTemplate. This enables dynamic binding of attributes, values, or elements based on the specific row being edited, and supports conditional rendering or modification of elements in the edit template based on the row’s state.
The following properties will be available at the time of template execution:
| Property Name | Usage |
|---|---|
isAdd |
A Boolean property that defines whether the current row is a new record or not. |
The following code example demonstrates the usage of the isAdd property in an edit template to disable the OrderID textbox when it’s not a new record:
<input id="OrderID" [(ngModel)]="data.OrderID" name="OrderID" type="text" [attr.disabled]="!data.isAdd ? '' : null">
Render editors as components
The Syncfusion® Angular Grid provides a powerful feature enabling dynamic rendering of Syncfusion® EJ2 controls as form editors during the editing process. This functionality delivers feature-rich controls for data entry within the edit form.
To achieve this by utilizing the actionComplete event of the Grid and specifying requestType as beginEdit or add.
The following code example illustrates rendering the DropDownList component in the actionComplete event.
actionComplete(args: DialogEditEventArgs) {
if ((args.requestType === 'beginEdit' || args.requestType === 'add')) {
let countryData: {}[] = DataUtil.distinct(data, 'ShipCountry', true) ;
new DropDownList({value: args.rowData.ShipCountry, popupHeight: '200px', floatLabelType: 'Always',
dataSource: countryData, fields: {text: 'ShipCountry', value: 'ShipCountry'}, placeholder: 'Ship Country'}, args.form.elements.namedItem('ShipCountry') as HTMLInputElement);
}
}Get value from editor
The get value from editor feature in the Syncfusion® Angular Grid enables reading, formatting, and updating the current editor value before saving. This feature provides significant value when specific actions must be performed on data, such as formatting or validation, before committing to the underlying data source.
To implement this feature, utilize the actionBegin event with the requestType set to save.
In the following code example, the freight value has been formatted and updated.
actionBegin(args: SaveEventArgs) {
if (args.requestType === 'save') {
// cast string to integer value.
(args.data as ColumnDataType).Freight = parseFloat(((args as any).form.querySelector('#Freight').ej2_instances[0] as HTMLInputElement).value);
}
}Set focus to a particular column editor
The Syncfusion® Angular Grid enables control of focus behavior for input elements in edit forms. By default, the first input element in the dialog receives focus when the dialog is opened. However, when the first input element is disabled or hidden, a different valid input element can receive focus. This can be achieved using the actionComplete event of the grid, where the requestType is set to beginEdit.
In the following code example, the “Customer ID” column receives focus.
actionComplete(args: DialogEditEventArgs) {
// Set initail Focus
if (args.requestType === 'beginEdit') {
((args.form as HTMLFormElement).elements.namedItem('CustomerID') as HTMLInputElement).focus();
}
}Disable default form validation
The Syncfusion® Angular Grid provides built-in support for Angular form validation to ensure data integrity and accuracy during editing. Scenarios may arise where disabling the default form validation rules is necessary. This can be achieved using the removeRules method within the actionComplete event of the grid.
To disable default form validation rules in the grid, use the following approach:
actionComplete(args: DialogEditEventArgs) {
if ((args.requestType === 'beginEdit' || args.requestType === 'add')) {
// Disable the Validation Rules
(args.form as HTMLFormElement)['ej2_instances'][0].removeRules();
}
}An alternative method to disable validation rules:
args.form.ej2_instances[0].rules = {}.
Add validation rules for custom editors
The Syncfusion® Angular Grid provides the ability to add validation rules for fields not present in the column model. This feature prevents erroneous or inconsistent data from being submitted, enhancing the reliability of application data.
To add validation rules, utilize the actionComplete event along with the addRules method.
The following approach uses the addRules method to add validation rules for custom editors in the actionComplete event:
Example:
actionComplete(args: DialogEditEventArgs) {
if ((args.requestType === 'beginEdit' || args.requestType === 'add')) {
// Add Validation Rules
(args.form as HTMLFormElement)['ej2_instances'][0].addRules('Freight', { max: 500 });
}
}Render tab component inside the dialog template
Rendering a Tab component inside the dialog template enhances the grid editing experience. This feature is especially useful for presenting multiple editing sections or categories in a tabbed layout, ensuring a more intuitive and easily navigable interface for data editing.
Enable dialog mode with editSettings.mode set to Dialog. Place the Tab component inside editSettingsTemplate.
The following example renders a tab component inside the edit dialog. The tab component has two tabs. Once fields in the first tab are filled and navigation to the second tab occurs, validation for the first tab is performed before proceeding.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser';
import { CommonModule } from '@angular/common';
import { GridModule, EditService, ToolbarService } from '@syncfusion/ej2-angular-grids'
import { ReactiveFormsModule, FormsModule } from '@angular/forms'
import { DropDownListAllModule } from '@syncfusion/ej2-angular-dropdowns'
import { TabAllModule,SelectingEventArgs,TabComponent } from '@syncfusion/ej2-angular-navigations'
import { DropDownList } from '@syncfusion/ej2-dropdowns';
import { Component, OnInit, ViewChild } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { DataUtil } from '@syncfusion/ej2-data';
import { data, ColumnDataType } from './datasource';
import { EditSettingsModel, ToolbarItems, GridComponent, DialogEditEventArgs } from '@syncfusion/ej2-angular-grids';
import { CheckBoxAllModule,ButtonModule} from '@syncfusion/ej2-angular-buttons';
import { NumericTextBoxAllModule } from '@syncfusion/ej2-angular-inputs';
@Component({
imports: [
ButtonModule,
CheckBoxAllModule,
TabAllModule,
GridModule,
DropDownListAllModule, ReactiveFormsModule, FormsModule,CommonModule,NumericTextBoxAllModule
],
providers: [EditService, ToolbarService],
standalone: true,
selector: 'app-root',
templateUrl: `tablikeedit.html`
})
export class AppComponent implements OnInit {
public data?: Object[];
public editSettings?: EditSettingsModel;
public toolbar?: ToolbarItems[];
public shipCountryDistinctData?: { [key: string]: Object }[];
@ViewChild('grid')
grid?: GridComponent;
@ViewChild('orderForm')
orderForm: FormGroup;
@ViewChild('tab')
tabObj: TabComponent;
ngOnInit(): void {
// Initialize component properties
this.data = data;
this.editSettings = { allowEditing: true, allowAdding: true, allowDeleting: true, mode: 'Dialog' };
this.toolbar = ['Add', 'Edit', 'Delete'];
this.shipCountryDistinctData = DataUtil.distinct(data, 'ShipCountry', true) as { [key: string]: Object }[];
}
// Handle completion of editing dialog
actionComplete(args: DialogEditEventArgs) {
if ((args.requestType === 'beginEdit' || args.requestType === 'add')) {
// Disable default validation.
(args.form as HTMLFormElement)['ej2_instances'][0].removeRules();
setTimeout(() => {
new DropDownList({
value: (args.rowData as ColumnDataType).ShipCountry!==undefined ?(args.rowData as ColumnDataType).ShipCountry : "Germany" ,
popupHeight: '200px',
floatLabelType: 'Always',
dataSource: this.shipCountryDistinctData,
placeholder:'ShipCountry',
fields: { text: 'ShipCountry', value: 'ShipCountry' }
}, (args.form as HTMLFormElement).elements.namedItem('ShipCountry') as HTMLInputElement);
}, 1);
// hide dialog button
(args.dialog as HTMLFormElement)['element'].querySelector('.e-footer-content').classList.add('e-hide');
// Add validation rules
(args.form as HTMLFormElement)['ej2_instances'][0].addRules('Freight', { max: 500 });
// Set initial focus
if (args.requestType === 'beginEdit') {
setTimeout(() => {
((args.form as HTMLFormElement).elements.namedItem('CustomerID') as HTMLInputElement).focus();
}, 1);
}
if(args.requestType === 'add') {
setTimeout(() => {
((args.form as HTMLFormElement).elements.namedItem('OrderID') as HTMLInputElement).focus();
}, 1);
}
}
}
// Move to the next tab
nextBtn() {
if (this.orderForm.valid)
this.moveNext();
}
// Move to the previous tab
previousBtn() {
this.movePrevious();
}
// Handle tab selection
selecting(e: SelectingEventArgs) {
if (e.isSwiped) e.cancel = true;
e.cancel = !this.orderForm.valid;
}
// Move to the next tab if the form is valid
moveNext() {
if (this.orderForm?.valid )
this.tabObj.select(1);
else
this.tabObj.select(1);
}
// Move to the previous tab if the form is valid
movePrevious() {
if (this.orderForm.valid)
this.tabObj.select(0);
}
// Handle submit button click
submitBtn() {
if (this.orderForm.valid)
(this.grid as GridComponent).endEdit();
}
}<ejs-grid #grid [dataSource]='data' allowPaging='true' [editSettings]='editSettings' [toolbar]='toolbar'
(actionComplete)='actionComplete($event)' height='285px'>
<e-columns>
<e-column field='OrderID' headerText='Order ID' width='120' textAlign='Right' [isPrimaryKey]='true'></e-column>
<e-column field='CustomerID' headerText='Customer Name' width='120'> </e-column>
<e-column field='ShipCountry' headerText='Ship Country' width='150'></e-column>
<e-column field='Freight' headerText='Freight' width='150'></e-column>
<e-column field='ShipAddress' headerText='Ship Address' width='150'></e-column>
<e-column field='Verified' headerText='Verified' width='100' type='boolean' [displayAsCheckBox]='true'></e-column>
</e-columns>
<ng-template #editSettingsTemplate let-data>
<div ngForm #orderForm="ngForm">
<ejs-tab #tab id="tab_wizard" showCloseButton=false (selecting)='selecting($event)'>
<e-tabitems>
<e-tabitem>
<ng-template #headerText>
<div> Details </div>
</ng-template>
<ng-template #content>
<div id="tab1">
<div class="form-row">
<div class="form-group col-md-6">
<div class="e-float-input e-control-wrapper"
[ngClass]="{'e-error': OrderID.invalid && (OrderID.touched || OrderID.dirty)}">
<input [(ngModel)]="data.OrderID" required id="OrderID" name="OrderID" type="text"
[disabled]="!data.isAdd" #OrderID="ngModel">
<span class="e-float-line"></span>
<label class="e-float-text e-label-top" for="OrderID"> Order ID</label>
</div>
<div id="OrderIDError" *ngIf='OrderID.invalid && (OrderID.dirty || OrderID.touched)'>
<label class="e-error" for="OrderID" id="OrderID-info" style="display: block;">*Order ID is
required</label>
</div>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<div class="e-float-input e-control-wrapper" [ngClass]="{'e-error': CustomerID.invalid && (CustomerID.dirty || CustomerID.touched)}">
<input [(ngModel)]="data.CustomerID" required id="CustomerID" name="CustomerID" type="text"
#CustomerID="ngModel">
<span class="e-float-line"></span>
<label class="e-float-text e-label-top" for="CustomerID">Customer Name</label>
</div>
<div id="CustomerIDError" *ngIf="CustomerID.invalid && (CustomerID.dirty || CustomerID.touched)">
<label class="e-error" for="CustomerID" id="CustomerID-info" style="display: block;">*Customer
Name is required</label>
</div>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<input required id="ShipCountry" name="ShipCountry" type="text">
</div>
</div>
<button ejs-button type="button" cssClass="e-info e-btn" style="float: right"
(click)="nextBtn()">next</button>
</div>
</ng-template></e-tabitem>
<e-tabitem>
<ng-template #headerText>
<div> Verify </div>
</ng-template>
<ng-template #content>
<div id="tab2">
<div class="form-row">
<div class="form-group col-md-6">
<div class="e-float-input e-control-wrapper"
[ngClass]="{'e-error': Freight.invalid && (Freight.dirty || Freight.touched)}">
<label class="e-float-text e-label-top" for="Freight">Freight</label>
<ejs-numerictextbox style="margin-top:10px" min='0' [(ngModel)]="data.Freight" required
id="Freight" name="Freight" #Freight="ngModel" floatLabelType='Always'></ejs-numerictextbox>
</div>
<div id="FreightError" *ngIf="Freight.invalid && (Freight.dirty || Freight.touched)">
<label class="e-error" for="Freight" id="Freight-info" style="display: block;">*Freight is
required</label>
</div>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<ejs-checkbox #Verified name="Verified" id="Verified" label="Verified"
[checked]="data.Verified"></ejs-checkbox>
</div>
</div>
<button ejs-button type="button" cssClass="e-info e-btn" style="float: right"
(click)="submitBtn()">Submit</button>
</div>
</ng-template>
</e-tabitem>
</e-tabitems>
</ejs-tab>
</div>
</ng-template>
</ejs-grid>import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));