Template editing in Angular TreeGrid component
15 May 202424 minutes to read
Reactive forms
Reactive Forms is a model-driven approach to create and manipulate the form controls. You can use reactive form to add and update the tree grid records. To use reactive forms for editing operation, you can take leverage of 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 tree grid editors.
In the below sample, We have created the FormGroup with FormControls for each columns, in the actionBegin event. While saving, we have validated the formgroup and updated the tree grid 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 the form controls. You can use template-driven form to add and update tree grid records. To use template-driven forms for editing operation, you can take leverage of 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 tree grid editors.
In some cases, you need to add the new field editors in the dialog which are not present in the column model. In that situation, the dialog template will help you to 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 below sample, We have created the FormGroup by using ngForm directive. While saving, we have validated the formgroup and updated the tree grid 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 you can 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 focused 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 have interested to use 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 have interested to use our default form validation, the validation rules for the fields which are not present in the column model need to be add 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 tree grid 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 Tree Grid. 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, we have rendered tab control 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 was done before navigate 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));