Detail template in Angular TreeGrid component
4 Sep 202522 minutes to read
The detail template in the TreeGrid component allows displaying additional information about a specific row in the TreeGrid. This feature is useful when additional data or custom content needs to be shown that is specific to each row in the TreeGrid. The detailTemplate property can be used to define an HTML template for the detail row. This template can include any HTML element or Angular component that needs to be displayed as detail content.
Here’s an example of using the detailTemplate
property in the TreeGrid:
import { Component, OnInit, ViewEncapsulation, ViewChild } from '@angular/core';
import { TreeGridComponent, DetailRowService } from '@syncfusion/ej2-angular-treegrid';
import { textdata } from './datasource';
import { Internationalization } from '@syncfusion/ej2-base';
let instance: Internationalization = new Internationalization();
@Component({
selector: 'app-container',
template: `<ejs-treegrid #treegrid [dataSource]='data' height=317 width='auto' childMapping= 'Children' >
<e-columns>
<e-column field='Name' headerText='First Name' width='160'></e-column>
<e-column field='DOB' headerText = 'DOB' width='105' type='date' format='yMd'></e-column>
<e-column field='Designation' headerText = 'Designation' width='180'></e-column>
<e-column field='Country' headerText = 'Country' width='148'></e-column>
</e-columns>
<ng-template #detailTemplate let-data>
<div>
<div style="position: relative; display: inline-block; float: left; font-weight: bold; width: 10%;padding:5px 4px 2px 27px;;">
<img src="{{data.FullName}}.png" alt="{{data.FullName}}" />
</div>
<div style="padding-left: 10px; display: inline-block; width: 66%; text-wrap: normal;font-size:13px;font-family:'Segoe UI';">
<div class="e-description" style="word-wrap: break-word;">
<b>{{data.Name}}</b> was born on {{format(data.DOB)}}. Now lives at {{data.Address}}, {{data.Country}}. {{data.Name}} holds a position of <b>{{data.Designation}}</b> in our WA department, (Seattle USA).
</div>
<div class="e-description" style="word-wrap: break-word;margin-top:5px;">
<b style="margin-right:10px;">Contact:</b>{{data.Contact}}
</div>
</div>
</div>
</ng-template>
</ejs-treegrid>`,
providers: [DetailRowService]
})
export class AppComponent implements OnInit {
public data?: Object[];
@ViewChild('treegrid')
public treegrid?: TreeGridComponent;
ngOnInit(): void {
this.data = textdata;
}
public format(value: Date): string {
return instance.formatDate(value, { skeleton: 'yMd', type: 'date' });
}
}
export interface DateFormat extends Window {
format?: Function;
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
Rendering custom component
The TreeGrid component provides a powerful feature that allows rendering custom components inside the detail row. This feature is helpful when additional information or functionality needs to be added for a specific row in the TreeGrid.
To render a custom component inside the detail row, define a template using the detailTemplate property and handle the detailDataBound event. This template can include any HTML element or Angular component that needs to be displayed as the detail content.
The detailDataBound
event is triggered after a detail row is bound to data. This event provides an object of type DetailDataBoundEventArgs as a parameter.
For example, to render grid inside the detail row, place an HTML div element as the detailTemplate
and render the DIV element as Grid component in the detailDataBound
event.
import { NgModule, ViewChild } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { TreeGridModule } from '@syncfusion/ej2-angular-treegrid'
import { GridModule } from '@syncfusion/ej2-angular-grids'
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { TreeGridComponent, DetailRowService, } from '@syncfusion/ej2-angular-treegrid';
import { sampleData, textdata } from './datasource';
import { Internationalization } from '@syncfusion/ej2-base';
import { DetailDataBoundEventArgs, Grid } from '@syncfusion/ej2-grids';
let instance: Internationalization = new Internationalization();
@Component({
imports: [TreeGridModule, GridModule],
standalone: true,
selector: 'app-container',
template: `<ejs-treegrid #treegrid [dataSource]='data' height=317 width='auto' childMapping= 'Children' (detailDataBound)='detailDataBound($event)' >
<e-columns>
<e-column field='Name' headerText='First Name' width='160'></e-column>
<e-column field='DOB' headerText = 'DOB' width='105' type='date' format='yMd'></e-column>
<e-column field='Designation' headerText = 'Designation' width='180'></e-column>
<e-column field='Country' headerText = 'Country' width='148'></e-column>
</e-columns>
<ng-template #detailTemplate let-data>
<div class = 'custom-grid' ></div>
</ng-template>
</ejs-treegrid>`,
providers: [DetailRowService],
})
export class AppComponent implements OnInit {
public data?: Object[];
@ViewChild('treegrid')
public treegrid?: TreeGridComponent;
ngOnInit(): void {
this.data = textdata;
}
detailDataBound(e: DetailDataBoundEventArgs) {
let detail = new Grid({
dataSource: sampleData,
columns: [
{ field: 'taskID', headerText: 'Order ID', width: 110 },
{ field: 'taskName', headerText: 'Customer Name', width: 140 },
{ field: 'priority', headerText: 'Ship Country', width: 150 },
],
});
detail.appendTo(
(e.detailElement as HTMLElement).querySelector(
'.custom-grid'
) as HTMLElement
);
}
public format(value: Date): string {
return instance.formatDate(value, { skeleton: 'yMd', type: 'date' });
}
}
export interface DateFormat extends Window {
format?: Function;
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
Custom button in custom column to hide or show detail template
The detail row can be displayed or concealed by utilizing a custom button through the column template feature of the TreeGrid.
The column template feature provides options to render a custom component in a TreeGrid column instead of a field value. This can be achieved by utilizing the template property of the TreeGrid. This property allows displaying custom elements in a column instead of the field value. It is advantageous when images, buttons, or other customized content needs to be displayed within a column.
For more information about column template, refer to this section.
Here’s an illustrative example showcasing how to implement showing/hiding a detail row using the column template. Utilize the column template to render a button. In the button click event, retrieve the detail row and add a CSS class to the detail row element. Based on the CSS class, the visibility of the detail row can be toggled.
import { Component, OnInit, ViewEncapsulation, ViewChild } from '@angular/core';
import {
TreeGridComponent,
DetailRowService,
} from '@syncfusion/ej2-angular-treegrid';
import { textdata } from './datasource';
import { Internationalization } from '@syncfusion/ej2-base';
import { CommandModel } from '@syncfusion/ej2-grids';
let instance: Internationalization = new Internationalization();
@Component({
selector: 'app-container',
encapsulation: ViewEncapsulation.None,
template: `<ejs-treegrid #treegrid [dataSource]='data' height=317 width='auto' childMapping= 'Children' >
<e-columns>
<e-column field='Name' headerText='First Name' width='160'></e-column>
<e-column field='DOB' headerText = 'DOB' width='105' type='date' format='yMd'></e-column>
<e-column field='Designation' headerText = 'Designation' width='180'></e-column>
<e-column field='Country' headerText = 'Country' width='148'></e-column>
<e-column headerText = 'Show or hide Button' width='250'>
<ng-template #template let-data>
<div class="e-section-control">
<button ejs-button cssClass="e-flat" content="Hide/Show Detail Row" (click)="detailrow($event)"></button>
</div>
</ng-template>
</e-column>
</e-columns>
<ng-template #detailTemplate let-data>
<div>
<div style="position: relative; display: inline-block; float: left; font-weight: bold; width: 10%;padding:5px 4px 2px 27px;;">
<img src="{{data.FullName}}.png" alt="{{data.FullName}}" />
</div>
<div style="padding-left: 10px; display: inline-block; width: 66%; text-wrap: normal;font-size:13px;font-family:'Segoe UI';">
<div class="e-description" style="word-wrap: break-word;">
<b>{{data.Name}}</b> was born on {{format(data.DOB)}}. Now lives at {{data.Address}}, {{data.Country}}. {{data.Name}} holds a position of <b>{{data.Designation}}</b> in our WA department, (Seattle USA).
</div>
<div class="e-description" style="word-wrap: break-word;margin-top:5px;">
<b style="margin-right:10px;">Contact:</b>{{data.Contact}}
</div>
</div>
</div>
</ng-template>
</ejs-treegrid>`,
styles: [
`.e-hidedetailrow{
display: none; /*//hide detailrow*/
}`,
],
providers: [DetailRowService],
})
export class AppComponent implements OnInit {
public data?: Object[];
@ViewChild('treegrid')
public treegrid?: TreeGridComponent;
ngOnInit(): void {
this.data = textdata;
}
detailrow(args: any) {
//Here get the corresponding row of the button clicked
var target_row = args.target.closest('.e-row');
//Check whether the next row is a detail row and if it is, determine if it is hidden or not.
if (
target_row.nextSibling.classList.contains('e-hidedetailrow') &&
target_row.nextSibling.classList.contains('e-detailrow')
) {
target_row.nextSibling.classList.remove('e-hidedetailrow');
} else if (target_row.nextSibling.classList.contains('e-detailrow')) {
target_row.nextSibling.classList.add('e-hidedetailrow');
}
}
public format(target_rowue: Date): string {
return instance.formatDate(target_rowue, { skeleton: 'yMd', type: 'date' });
}
}
export interface DateFormat extends Window {
format?: Function;
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
Render detail template for only parent records
In the TreeGrid, the detail row can be rendered exclusively for parent records based on a condition. The detailTemplate property allows including any HTML element or Angular component that needs to be displayed as the detail content, contingent on a condition.
The hasChildRecords
property can be used to determine whether a record has child records, making it useful for conditionally rendering detail templates only for parent records.
In the following demonstration, the detail row is presented only for parent records using a condition in the ng-template.
import { Component, OnInit, ViewEncapsulation, ViewChild } from '@angular/core';
import {
TreeGridComponent,
DetailRowService,
} from '@syncfusion/ej2-angular-treegrid';
import { textdata } from './datasource';
import { Internationalization } from '@syncfusion/ej2-base';
let instance: Internationalization = new Internationalization();
@Component({
selector: 'app-container',
template: `<ejs-treegrid #treegrid [dataSource]='data' height=317 width='auto' childMapping= 'Children' >
<e-columns>
<e-column field='Name' headerText='First Name' width='160'></e-column>
<e-column field='DOB' headerText = 'DOB' width='105' type='date' format='yMd'></e-column>
<e-column field='Designation' headerText = 'Designation' width='180'></e-column>
<e-column field='Country' headerText = 'Country' width='148'></e-column>
</e-columns>
<ng-template #detailTemplate let-data>
<div *ngIf="data.hasChildRecords">
<div style="position: relative; display: inline-block; float: left; font-weight: bold; width: 10%;padding:5px 4px 2px 27px;;">
<img src="{{data.FullName}}.png" alt="{{data.FullName}}" />
</div>
<div style="padding-left: 10px; display: inline-block; width: 66%; text-wrap: normal;font-size:13px;font-family:'Segoe UI';">
<div class="e-description" style="word-wrap: break-word;">
<b>{{data.Name}}</b> was born on {{format(data.DOB)}}. Now lives at {{data.Address}}, {{data.Country}}. {{data.Name}} holds a position of <b>{{data.Designation}}</b> in our WA department, (Seattle USA).
</div>
<div class="e-description" style="word-wrap: break-word;margin-top:5px;">
<b style="margin-right:10px;">Contact:</b>{{data.Contact}}
</div>
</div>
</div>
</ng-template>
</ejs-treegrid>`,
providers: [DetailRowService],
})
export class AppComponent implements OnInit {
public data?: Object[];
@ViewChild('treegrid')
public treegrid?: TreeGridComponent;
ngOnInit(): void {
this.data = textdata;
}
public format(value: Date): string {
return instance.formatDate(value, { skeleton: 'yMd', type: 'date' });
}
}
export interface DateFormat extends Window {
format?: Function;
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
Limitations
Detail template is not supported with the following features:
- Frozen rows and columns
- Immutable mode
- Infinite scrolling
- Virtual scrolling
- Row template
- Row spanning
- Column spanning
- State persistence