Template editing in Angular TreeGrid component
8 Sep 202524 minutes to read
Reactive forms
Reactive Forms is a model-driven approach to create and manipulate form controls. You can use reactive forms to add and update TreeGrid records. To use reactive forms for editing operations, you can leverage the template support of dialog or row edit mode. Setting the editSettings.mode as Row/Dialog and editSettingsTemplate as template variable of NgTemplate to define the TreeGrid editors.
In the following sample, the FormGroup with FormControls is created for each column in the actionBegin event. While saving, the formgroup is validated and the TreeGrid is updated with the edited data from the FormGroup object:
import { NgModule,ViewChild } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { TreeGridModule } from '@syncfusion/ej2-angular-treegrid'
import { PageService, SortService, FilterService,EditService,ToolbarService } from '@syncfusion/ej2-angular-treegrid'
import {ButtonModule} from '@syncfusion/ej2-angular-buttons'
import { DropDownListAllModule } from '@syncfusion/ej2-angular-dropdowns'
import { ReactiveFormsModule , FormsModule} from '@angular/forms'
import { NumericTextBoxAllModule } from '@syncfusion/ej2-angular-inputs'
import { DatePickerModule, DatePickerAllModule } from '@syncfusion/ej2-angular-calendars'
import { CommonModule } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { sampleData } from './datasource';
import { EditSettingsModel, ToolbarItems } from '@syncfusion/ej2-angular-treegrid';
import { DialogEditEventArgs, SaveEventArgs } from '@syncfusion/ej2-angular-grids';
import { Dialog } from '@syncfusion/ej2-angular-popups';
import { FormGroup, AbstractControl, FormControl, Validators } from '@angular/forms';
import { DataUtil } from '@syncfusion/ej2-data';
import { Browser } from '@syncfusion/ej2-base';
@Component({
imports: [
CommonModule,
TreeGridModule,
ButtonModule,
DropDownListAllModule,
ReactiveFormsModule,
FormsModule,
NumericTextBoxAllModule,
DatePickerAllModule
],
providers: [PageService,
SortService,
FilterService,
EditService,
ToolbarService],
standalone: true,
selector: 'app-container',
template: `<ejs-treegrid [dataSource]='data' [toolbar]='toolbarOptions' [treeColumnIndex]='1' height='270' [editSettings]='editSettings' childMapping='subtasks' (actionBegin)="actionBegin($event)" (actionComplete)="actionComplete($event)">
<e-columns>
<e-column field='taskID' headerText='Task ID' width='120' textAlign='Right' isPrimaryKey='true' ></e-column>
<e-column field='taskName' headerText='Task Name' width='225' ></e-column>
<e-column field='duration' headerText='Duration' width='90' textAlign='Right' ></e-column>
<e-column field='progress' headerText='Progress' width='90' textAlign='Right' ></e-column>
</e-columns>
<ng-template #editSettingsTemplate let-data>
<div [formGroup]="taskForm">
<table class="e-table e-inline-edit" cellspacing="0.25">
<colgroup>
<col style="width: 120px;">
<col style="width: 225px;">
<col style="width: 90px;">
<col style="width: 90px;">
</colgroup>
<tbody>
<tr>
<td style="text-align: right" class='e-rowcell'>
<div class="e-float-input e-control-wrapper" [ngClass]="{'e-error': taskID.invalid && (taskID.dirty || taskID.touched)}">
<input formControlName="taskID" data-msg-containerid='taskIDError' id="taskID" name="taskID" type="text" [attr.disabled]="!data.isAdd ? '' : null">
<span class="e-float-line"></span>
<label class="e-float-text e-label-top" for="taskID"> Task ID</label>
</div>
<div id="taskIDError" [style.visibility]='((taskID.invalid && (taskID.dirty || taskID.touched)) || (taskID.invalid && submitClicked))? "visible": "hidden"'>
<label class="e-error" for="taskID" id="taskID-info" style="display: block;">*Task ID is required</label>
</div>
</td>
<td class='e-rowcell'>
<div class="e-float-input e-control-wrapper" [ngClass]="{'e-error': taskName.invalid && (taskName.dirty || taskName.touched)}">
<input formControlName="taskName" data-msg-containerid='taskNameError' id="taskName" name="taskName" type="text">
<span class="e-float-line"></span>
<label class="e-float-text e-label-top" for="taskName">Task Name</label>
</div>
<div id="taskNameError" [style.visibility]='((taskName.invalid && (taskName.dirty || taskName.touched)) || (taskName.invalid && submitClicked))? "visible": "hidden"'>
<label class="e-error" for="taskName" id="taskName-info" style="display: block;">*Task Name is required</label>
</div>
</td>
<td class='e-rowcell'>
<ejs-numerictextbox formControlName="duration" id="duration" placeholder="Duration" format="##" floatLabelType='Always'></ejs-numerictextbox>
</td>
<td class='e-rowcell'>
<ejs-dropdownlist id="progress" formControlName="progress" [dataSource]='progressDistinctData' [fields]="{text: 'progress', value: 'progress' }" placeholder="Progress" popupHeight='300px' floatLabelType='Always'></ejs-dropdownlist>
</td>
</tr>
</tbody>
</table>
</div>
</ng-template>
</ejs-treegrid>`,
})
export class AppComponent implements OnInit {
public data: Object[] = [];
public editSettings?: EditSettingsModel;
public toolbarOptions?: ToolbarItems[];
public taskForm?: FormGroup | any;
public progressDistinctData?: Object;
public priorityDistinctData?: Object;
public submitClicked: boolean = false;
toolbar: any;
ngOnInit(): void {
this.data = sampleData;
this.editSettings = { allowEditing: true, allowAdding: true, allowDeleting: true, mode:"Row", newRowPosition: 'Below'};
this.toolbarOptions = ['Add', 'Edit', 'Delete','Update','Cancel'];
this.progressDistinctData = DataUtil.distinct(sampleData, 'progress', true);
this.priorityDistinctData = DataUtil.distinct(sampleData, 'priority', true );
}
createFormGroup(data: ITaskModel): FormGroup {
return new FormGroup({
taskID: new FormControl(data.taskID, Validators.required),
startDate: new FormControl(data.startDate, this.dateValidator()),
taskName: new FormControl(data.taskName, Validators.required),
duration: new FormControl(data.duration),
progress: new FormControl(data.progress),
priority: new FormControl(data.priority),
});
}
dateValidator(): Object {
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 | any): void {
if (args.requestType === 'beginEdit' || args.requestType === 'add') {
this.submitClicked = false;
this.taskForm = this.createFormGroup(args.rowData);
}
if (args.requestType === 'save') {
this.submitClicked = true;
if ((this.taskForm as FormGroup).valid) {
args.data = (this.taskForm as FormGroup).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('taskName') as HTMLInputElement).focus();
} else if (args.requestType === 'add') {
((args.form as HTMLFormElement).elements.namedItem('taskID') as HTMLInputElement).focus();
}
}
}
get taskID(): AbstractControl { return (this.taskForm as FormGroup).get('taskID') as AbstractControl; }
get taskName(): AbstractControl { return (this.taskForm as FormGroup).get('taskName') as AbstractControl; }
get startDate(): AbstractControl { return (this.taskForm as FormGroup).get('startDate') as AbstractControl; }
}
export interface ITaskModel {
taskID?: number;
taskName?: string;
startDate?: Date;
duration?: number;
progress?: number;
priority?: string;
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
Template-driven forms
Template-driven forms is a template-driven approach to create and manipulate form controls. You can use template-driven forms to add and update TreeGrid records. To use template-driven forms for editing operations, you can leverage the template support of dialog or row edit mode. Setting the editSettings.mode as Row/Dialog
and editSettingsTemplate
as template variable of NgTemplate to define the TreeGrid editors.
In some cases, you need to add new field editors in the dialog which are not present in the column model. In that situation, the dialog template will help you customize the default edit dialog.
You can check this video to learn about how to customize the edit dialog of TreeGrid using template driven forms.
In the following sample, the FormGroup is created using ngForm directive. While saving, the formgroup is validated and the TreeGrid is updated with the edited model data:
import { NgModule,ViewChild } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { CommonModule } from '@angular/common'
import { TreeGridModule } from '@syncfusion/ej2-angular-treegrid'
import { PageService, FilterService,EditService,ToolbarService } from '@syncfusion/ej2-angular-treegrid'
import {ButtonModule, CheckBoxAllModule} from '@syncfusion/ej2-angular-buttons'
import { DropDownListAllModule } from '@syncfusion/ej2-angular-dropdowns'
import { ReactiveFormsModule , FormsModule} from '@angular/forms'
import { NumericTextBoxAllModule } from '@syncfusion/ej2-angular-inputs'
import { DatePickerAllModule } from '@syncfusion/ej2-angular-calendars'
import { Component, OnInit, } from '@angular/core';
import { sampleData } from './datasource';
import { DataUtil } from '@syncfusion/ej2-data';
import { DialogEditEventArgs, SaveEventArgs } from '@syncfusion/ej2-angular-grids';
import { FormGroup } from '@angular/forms';
@Component({
imports: [
CommonModule,
TreeGridModule,
ButtonModule,
DropDownListAllModule,
ReactiveFormsModule,
FormsModule,
NumericTextBoxAllModule,
CheckBoxAllModule,
DatePickerAllModule
],
providers: [PageService,
FilterService,
EditService,
ToolbarService],
standalone: true,
selector: 'app-container',
template: `<ejs-treegrid [dataSource]='data' height='225' childMapping='subtasks' [treeColumnIndex]='1'allowPaging='true' [pageSettings]='pageSettings' [editSettings]='editSettings' [toolbar]='toolbar' (actionBegin)="actionBegin($event)" (actionComplete)="actionComplete($event)">
<e-columns>
<e-column field='taskID' headerText='Task ID' width='120' textAlign='Right' isPrimaryKey='true' ></e-column>
<e-column field='taskName' headerText='Task Name' width='225' ></e-column>
<e-column field='startDate' headerText='Start Date' width='150' format="yMd" ></e-column>
<e-column field='approved' headerText='Approved' type='boolean' editType='booleanedit' [displayAsCheckBox]='true' width='90' textAlign='Right' ></e-column>
</e-columns>
<ng-template #editSettingsTemplate let-data>
<div ngForm #taskForm="ngForm">
<div class="form-row">
<div class="form-group col-md-6">
<div class="e-float-input e-control-wrapper" [ngClass]="{'e-error': taskID.invalid && (taskID.dirty || taskID.touched)}">
<input [(ngModel)]="taskData.taskID" required id="taskID" name="taskID" type="text" [attr.disabled]="!data.isAdd ? '' : null" #taskID="ngModel">
<span class="e-float-line"></span>
<label class="e-float-text e-label-top" for="taskID"> Task ID</label>
</div>
<div id="taskIDError" *ngIf='taskID.invalid && (taskID.dirty || taskID.touched)'>
<label class="e-error" id="taskID-info" style="display: block;">*Task ID is required</label>
</div>
</div>
<div class="form-group col-md-6">
<div class="e-float-input e-control-wrapper" [ngClass]="{'e-error': taskName.invalid && (taskName.dirty || taskName.touched)}">
<input [(ngModel)]="taskData.taskName" required id="taskName" name="taskName" type="text" #taskName="ngModel">
<span class="e-float-line"></span>
<label class="e-float-text e-label-top" for="taskName">Task Name</label>
</div>
<div id="taskNameError" *ngIf='taskName.invalid && (taskName.dirty || taskName.touched)'>
<label class="e-error" id="taskName-info" style="display: block;">*Task Name is required</label>
</div>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<ejs-numerictextbox [(ngModel)]="taskData.progress" name="progress" id="progress" placeholder="Progress" floatLabelType='Always'></ejs-numerictextbox>
</div>
<div class="form-group col-md-6">
<ejs-datepicker id="startDate" name="startDate" required [(ngModel)]="taskData.startDate" placeholder="Start Date" floatLabelType='Always'></ejs-datepicker>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<ejs-numerictextbox [(ngModel)]="taskData.duration" name="duration" id="duration" placeholder="Duration" floatLabelType='Always'></ejs-numerictextbox>
</div>
<div class="form-group col-md-3">
<ejs-checkbox #approved label='Approved' [(ngModel)]="taskData.approved" [ngModelOptions]="{standalone: true}" [checked]="taskData.approved"></ejs-checkbox>
</div>
</div>
</div>
</ng-template>
</ejs-treegrid>`,
})
export class AppComponent implements OnInit {
public data: Object[] = [];
public editSettings?: Object;
public toolbar?: string[];
public pageSettings?: Object;
public taskData?: ITaskModel | any;
@ViewChild('taskForm')
public taskForm?: FormGroup;
public progressDistinctData?: Object;
public priorityDistinctData?: Object;
ngOnInit(): void {
this.data = sampleData;
this.editSettings = { allowEditing: true, allowAdding: true, allowDeleting: true , mode: 'Dialog' ,newRowPosition: 'Below'};
this.toolbar = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];
this.pageSettings = { pageCount: 5 };
this.progressDistinctData = DataUtil.distinct(sampleData, 'progress', true);
this.priorityDistinctData = DataUtil.distinct(sampleData, 'priority', true );
}
actionBegin(args: SaveEventArgs): void {
if (args.requestType === 'beginEdit' || args.requestType === 'add') {
this.taskData = Object.assign({}, args.rowData);
}
if (args.requestType === 'save') {
if ((this.taskForm as FormGroup).valid) {
args.data = this.taskData;
} else {
args.cancel = true;
}
}
}
actionComplete(args: DialogEditEventArgs): void {
if (args.requestType === 'beginEdit' || args.requestType === 'add') {
// Disable the Validation Rules
// Disable the Validation Rules
(args.form as HTMLFormElement)['ej2_instances'][0].rules = {};
// Set initial Focus
if (args.requestType === 'beginEdit') {
((args.form as HTMLFormElement).elements.namedItem('taskName') as HTMLInputElement).focus();
} else if (args.requestType === 'add') {
((args.form as HTMLFormElement).elements.namedItem('taskID') as HTMLInputElement).focus();
}
}
}
public focusIn(target: HTMLElement): void {
(target.parentElement as HTMLElement).classList.add('e-input-focus');
}
public focusOut(target: HTMLElement): void {
(target.parentElement as HTMLElement).classList.remove('e-input-focus');
}
}
export interface ITaskModel {
taskID?: number;
taskName?: string;
startDate?: Date;
duration?: number;
progress?: number;
priority?: string;
approved?: boolean;
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
The template form editors should have name attribute.
Template context
While using the edit template, you can access the row information inside the NgTemplate and bind the attributes or values or elements based on this row information.
The following properties will be available at the time of template execution:
Property Name | Usage |
---|---|
isAdd | A boolean property; it defines whether the current row should be a new record or not. |
In the following code example, the taskID textbox has been disabled by using the isAdd property:
// The disabled attributes will be added based on the isAdd property.
<input formControlName="taskID" id="taskID" name="taskID" type="text" [attr.disabled]="!data.isAdd ? '' : null">
The following code example illustrates rendering the taskID textbox, when a new record is added:
<div class="form-group col-md-6" *ngIf='data.isAdd'>
<div class="e-float-input e-control-wrapper">
<input formControlName="taskID" id="taskID" name="taskID" type="text" [attr.disabled]="!data.isAdd ? '' : null">
<span class="e-float-line"></span>
<label class="e-float-text e-label-top" for="taskID"> Task ID</label>
</div>
</div>
Set focus to editor
By default, the first input element in the dialog will be focused while opening the dialog. If the first input element is in disabled or hidden state then you need to focus the valid input element in the actionComplete event based on requestType as beginEdit.
actionComplete: (args: DialogEditEventArgs) => {
// Set initial Focus
if (args.requestType === 'beginEdit') {
(args.form.elements.namedItem('taskName')as HTMLInputElement).focus();
}
}
Disable form validation
If you are interested in using angular form validation then you need to disable the default validation rules in the actionComplete event.
actionComplete(args: DialogEditEventArgs) {
if ((args.requestType === 'beginEdit' || args.requestType === 'add')) {
// Disable the Validation Rules
args.form.ej2_instances[0].rules = {};
}
}
Adding validation rules for custom editors
If you are interested in using our default form validation, the validation rules for the fields which are not present in the column model need to be added in the actionComplete event.
actionComplete: (args: DialogEditEventArgs) => {
if ((args.requestType === 'beginEdit' || args.requestType === 'add')) {
// Add Validation Rules
args.form.ej2_instances[0].addRules('progress', {max: 100});
}
}
Render tab component inside the dialog template
You can use Tab component inside dialog edit UI using dialog template feature. The dialog template feature can be enabled by defining editSettings.mode as Dialog
and editSettingsTemplate as template variable in NgTemplate to define the TreeGrid editors.
To include tab components in the Dialog, please ensure the following steps:
Step 1: To render the Tab component, use the editSettingsTemplate
of the TreeGrid. Inside the content template of the tab items define the input elements.
<ejs-tab #tab id="tab_wizard" showCloseButton=false (selecting)='selecting($event)'>
<e-tabitems>
<e-tabitem [header]="{ 'text': 'Details' }" >
<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': taskID.invalid && (taskID.dirty || taskID.touched)}">
<input [(ngModel)]="data.taskID" required id="taskID" name="taskID" type="text" [attr.disabled]="!data.isAdd ? '' : null" #taskID="ngModel">
<span class="e-float-line"></span>
<label class="e-float-text e-label-top" for="taskID"> Task ID</label>
</div>
<div id="taskIDError" *ngIf='taskID.invalid && (taskID.dirty || taskID.touched)'>
<label class="e-error" for="taskID" id="taskID-info" style="display: block;">*Task 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': taskName.invalid && (taskName.dirty || taskName.touched)}">
<input [(ngModel)]="data.taskName" required id="taskName" name="taskName" type="text" #taskName="ngModel">
<span class="e-float-line"></span>
<label class="e-float-text e-label-top" for="taskName">Task Name</label>
</div>
<div id="taskNameError" *ngIf='taskName.invalid && (taskName.dirty || taskName.touched)'>
<label class="e-error" for="taskName" id="taskName-info" style="display: block;">*Customer Name is required</label>
</div>
</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 [header]="{ 'text': 'Verify' }">
<ng-template #content>
<div id="tab2">
<div class="form-row" >
<div class="form-group col-md-6">
<ejs-dropdownlist id="priority" name="priority" [(ngModel)]="data.priority" [dataSource]='priorityDistinctData' [fields]="{text: 'priority', value: 'priority' }" placeholder="Priority" popupHeight='300px' floatLabelType='Always'></ejs-dropdownlist>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<ejs-checkbox #approved name="approved" id="approved" label="Approved" [checked]="data.approved" ></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>
In the following example, tab control is rendered inside the edit dialog. The tab control has two tabs and once you fill the first tab and navigate to second one, the validation for first tab is done before navigating to second:
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { TreeGridModule, EditService, ToolbarService, TreeGridAllModule } from '@syncfusion/ej2-angular-treegrid'
import { ReactiveFormsModule, FormsModule } from '@angular/forms'
import { DropDownListAllModule } from '@syncfusion/ej2-angular-dropdowns'
import { TabAllModule } from '@syncfusion/ej2-angular-navigations'
import { CommonModule } from '@angular/common';
import { Component, OnInit, ViewChild } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { DataUtil } from '@syncfusion/ej2-data';
import { sampleData } from './datasource';
import { EditSettingsModel, ToolbarItems, GridComponent, DialogEditEventArgs } from '@syncfusion/ej2-angular-grids';
import { TreeGridComponent } from '@syncfusion/ej2-angular-treegrid'
import { ButtonModule, CheckBoxAllModule } from '@syncfusion/ej2-angular-buttons'
@Component({
imports: [
CommonModule,
ButtonModule,
CheckBoxAllModule,
TabAllModule,
TreeGridAllModule,
DropDownListAllModule, ReactiveFormsModule, FormsModule
],
providers: [EditService, ToolbarService],
standalone: true,
selector: 'app-container',
template: `<ejs-treegrid #grid [dataSource]='data' height='225' childMapping='subtasks' allowPaging='true' [editSettings]='editSettings' [toolbar]='toolbar' (actionComplete)='actionComplete($event)'>
<e-columns>
<e-column field='taskID' headerText='Task ID' width='120' textAlign='Right' [isPrimaryKey]='true'></e-column>
<e-column field='taskName' headerText='Task Name' width='120'></e-column>
<e-column field='priority' headerText='Priority' width='150'></e-column>
<e-column field='approved' headerText='Approved' width='100' type='boolean' [displayAsCheckBox]='true'></e-column>
</e-columns>
<ng-template #editSettingsTemplate let-data>
<div ngForm #taskForm="ngForm">
<ejs-tab #tab id="tab_wizard" showCloseButton=false (selecting)='selecting($event)'>
<e-tabitems>
<e-tabitem [header]="{ 'text': 'Details' }" >
<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': taskID.invalid && (taskID.dirty || taskID.touched)}">
<input [(ngModel)]="data.taskID" required id="taskID" name="taskID" type="text" [attr.disabled]="!data.isAdd ? '' : null" #taskID="ngModel">
<span class="e-float-line"></span>
<label class="e-float-text e-label-top" for="taskID"> Task ID</label>
</div>
<div id="taskIDError" *ngIf='taskID.invalid && (taskID.dirty || taskID.touched)'>
<label class="e-error" for="taskID" id="taskID-info" style="display: block;">*Task 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': taskName.invalid && (taskName.dirty || taskName.touched)}">
<input [(ngModel)]="data.taskName" required id="taskName" name="taskName" type="text" #taskName="ngModel">
<span class="e-float-line"></span>
<label class="e-float-text e-label-top" for="taskName">Task Name</label>
</div>
<div id="taskNameError" *ngIf='taskName.invalid && (taskName.dirty || taskName.touched)'>
<label class="e-error" for="taskName" id="taskName-info" style="display: block;">*Customer Name is required</label>
</div>
</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 [header]="{ 'text': 'Verify' }">
<ng-template #content>
<div id="tab2">
<div class="form-row" >
<div class="form-group col-md-6">
<ejs-dropdownlist id="priority" name="priority" [(ngModel)]="data.priority" [dataSource]='priorityDistinctData' [fields]="{text: 'priority', value: 'priority' }" placeholder="Priority" popupHeight='300px' floatLabelType='Always'></ejs-dropdownlist>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<ejs-checkbox #approved name="approved" id="approved" label="Approved" [checked]="data.approved" ></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-treegrid>`
})
export class AppComponent implements OnInit {
public data: any;
public editSettings?: EditSettingsModel;
public toolbar?: ToolbarItems[];
public priorityDistinctData?: Object;
@ViewChild('grid')
grid?: TreeGridComponent;
@ViewChild('taskForm')
taskForm?: FormGroup;
@ViewChild('tab')
tabObj: any;
ngOnInit(): void {
this.data = sampleData;
this.editSettings = { allowEditing: true, allowAdding: true, allowDeleting: true, mode: 'Dialog' };
this.toolbar = ['Add', 'Edit', 'Delete','Update','Cancel'];
this.priorityDistinctData = DataUtil.distinct(sampleData, 'priority', true );
}
actionComplete(args: any) {
if (((args as any).requestType === 'beginEdit' || (args as any).requestType === 'add')) {
// Disable default validation.
(args as any).form.ej2_instances[0].rules = {};
const dialogInstance = (args as any).dialog;
dialogInstance.buttons = [];
}
}
nextBtn() {
this.moveNext();
}
selecting(e: any) {
if(e.isSwiped){
e.cancel = true;
}
if(e.selectingIndex === 1) {
e.cancel = !this.taskForm?.valid;
}
}
moveNext() {
if (this.taskForm?.valid) {
this.tabObj.select(1);
}
}
submitBtn() {
if (this.taskForm?.valid) {
this.grid?.endEdit();
}
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));