- Home
- Forum
- Angular - EJ 2
- Grid child
Grid child
13 Replies
1 reply marked as answer
RS
Rajapandiyan Settu
Syncfusion Team
December 30, 2020 12:06 PM UTC
Hi Vin,
Thanks for contacting Syncfusion support.
Query: How do i adda link to child grid record
You can achieve your requirement by using columnTemplate feature. By using this we can render the custom element inside the column.
columnTemplate Doc: https://ej2.syncfusion.com/angular/documentation/grid/columns/#column-template
By default, the child-Grid is rendered in typescript way. So, you can define template string in the columnTemplate. Refer to the below code example.
columnTemplate API: https://ej2.syncfusion.com/angular/documentation/api/grid/column/#template
|
this.childGrid = {
dataSource: orderDatas,
queryString: "EmployeeID",
----
columns: [
----
{
field: "ShipName",
headerText: "Ship Name",
// render the template element as htmlstring
template: "<div><a rel='nofollow' href='https://ej2.syncfusion.com/documentation/grid/'> ${ShipName}</a></div>",
width: 150
}
]
}; |
If you want to render the Child-Grid’s column template in angular way then use the below code example.
|
[app.component.html]
// render the child-Grid’s column template elements inside the ng-template
<ng-template #childtemplate let-data>
<div>
</div>
</ng-template>
[app.component.ts]
import {Component, OnInit, ViewEncapsulation, ViewContainerRef, ViewChild, TemplateRef, Inject } from "@angular/core";
----
@Component({
selector: "app-root",
templateUrl: "app.component.html",
providers: [DetailRowService]
})
export class AppComponent {
constructor(
@Inject(ViewContainerRef) private viewContainerRef?: ViewContainerRef
) {}
@ViewChild("grid", { static: true })
public grid: GridComponent;
@ViewChild("childtemplate", { static: true })
public childtemplate: any;
public parentData: Object[];
public childGrid: any;
ngOnInit(): void {
this.parentData = employeeData;
this.childGrid = {
dataSource: orderDatas,
queryString: "EmployeeID",
allowPaging: true,
pageSettings: { pageSize: 6, pageCount: 5 },
load: function() {
this.registeredTemplate = {}; //set registertemplate value as empty in load event
},
columns: [
{
field: "OrderID",
headerText: "Order ID",
textAlign: "Right",
width: 120
},
{
field: "ShipCity",
headerText: "Ship City",
template: this.childtemplate, // render ng template in the column
width: 120
}
]
};
}
ngAfterViewInit() {
this.childtemplate.elementRef.nativeElement._viewContainerRef = this.viewContainerRef;
}
} |
Find the below sample for your reference.
Please get back to us if you need further assistance with this.
Regards,
Rajapandiyan S
VI
vin
December 31, 2020 02:18 AM UTC
I am not getting the click method
showTaskRedirect(args){
console.log('showTaskRedirect');
}
{
field: "itemName",
headerText: "Name",
textAlign: "left",
template:
"<div><a rel='nofollow' href='javascript:void(0);' (click)='showTaskRedirect($event)'> ${itemName}</a></div>",
width: 120
},
RS
Rajapandiyan Settu
Syncfusion Team
December 31, 2020 10:12 AM UTC
Hi Vin,
Thanks for your update.
Query: I am not getting the click method
Be default, the template string accepts only the pure html element definition. So, we need define the event in html way instead of using angular way. For this, we need to define the correspond event function in the window instances.
We have prepared a sample based on this. Refer to the below code example and sample for more information.
|
export class AppComponent {
-----
ngOnInit(): void {
this.childGrid = {
----
columns: [
---
{
field: "ShipName",
headerText: "Ship Name",
template:
"<div><a rel='nofollow' href='https://ej2.syncfusion.com/documentation/grid/' onClick='myfunction(event)'> ${ShipName}</a></div>",
width: 150
}
]
};
}
}
(window as any).myfunction = function(args) {
console.log(args);
};
|
Please get back to us if you need further assistance with this.
Regards,
Rajapandiyan S
VI
vin
January 2, 2021 08:40 PM UTC
from the Window function, i am not able to access any component method
inside component
redirectToBacklog(args){
console.log('redirect IN', this.router);
var getRouteLink = "/project-charts/backlog"
this.router.navigateByUrl(getRouteLink);
}
i am getting this.router as undefined!!
outside component
(window as any).myfunction = function(args) {
console.log(args);
SprintsComponent.prototype.redirectToBacklog(args);
};
RS
Rajapandiyan Settu
Syncfusion Team
January 4, 2021 12:27 PM UTC
Hi Vin,
Thanks for your update.
Query: from the Window function, i am not able to access any component method
Be default, the component instances are not available inside the window object.
So, we kindly suggested you use ng-template for the chilGrid’s column template to access the component instances. Find the below code example and sample for your reference.
|
[app.component.html]
<ng-template #childtemplate let-data>
<div>
<a rel='nofollow' href="https://ej2.syncfusion.com/documentation/grid/" (click)="hyperclick($event)">{{data.ShipCity}}</a>
</div>
</ng-template>
[app.component.ts]
export class AppComponent {
-----
hyperclick(args) {
console.log(this);
console.log(args);
}
}
|
Please get back to us if you need further assistance with this.
Regards,
Rajapandiyan S
VI
vin
January 7, 2021 08:44 PM UTC
The link is NOT showing UP for some reason with ng-template
The only difference is i call this.childGridDataBind(); after i get data for parent grid using this.getParentGridData()

<ng-template #childtemplate let-data>
<div>
<a rel='nofollow' rel='nofollow' href="https://ej2.syncfusion.com/documentation/grid/" (click)="hyperclick($event)">{{data.itemName}}a>
div>
ng-template>
import { Component,TemplateRef, Inject, AfterViewInit, ViewContainerRef, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
import { EditSettingsModel, CellEditArgs, ToolbarItems, IEditCell, CommandModel, ContextMenuItemModel, FilterSettingsModel, SaveEventArgs, GridComponent, Column } from '@syncfusion/ej2-angular-grids';
import { PageSettingsModel, CommandClickEventArgs } from '@syncfusion/ej2-angular-grids';
import { ProjectChartsService } from '../project-charts.service';
import { LeftNavService } from 'src/app/onboarding/left-nav.service';
import { TabComponent } from '@syncfusion/ej2-angular-navigations';
import { ClickEventArgs, EventArgs } from '@syncfusion/ej2-angular-navigations';
import { DialogComponent } from '@syncfusion/ej2-angular-popups';
import { EmitType } from '@syncfusion/ej2-base';
import { GroupSettingsModel,parentsUntil,DetailRowService } from '@syncfusion/ej2-angular-grids';
import { AnimationModel, RangeColorModel, ProgressBar } from '@syncfusion/ej2-progressbar';
import { ProgressTheme, ILoadedEventArgs } from '@syncfusion/ej2-progressbar';
import { FontModel } from '@syncfusion/ej2-angular-charts';
import { Router } from '@angular/router';
@Component({
selector: 'app-sprints',
templateUrl: './sprints.component.html',
styleUrls: ['./sprints.component.css'],
providers: [DetailRowService]
})
export class SprintsComponent implements OnInit, AfterViewInit {
@ViewChild("grid", { static: false }) grid: GridComponent;
@ViewChild('element', { static: true }) element;
@ViewChild('tabsElement', { static: false }) tabInstance: TabComponent;
@ViewChild('ejDialog', { static: false }) ejDialog: DialogComponent;
@ViewChild('progress', { static: false }) public progress: ProgressBar;
@ViewChild("childtemplate", { static: true }) public childtemplate: any;
hyperclick(args) {
console.log(this);
console.log(args);
}
ngAfterViewInit() {
this.childtemplate.elementRef.nativeElement._viewContainerRef = this.viewContainerRef;
}
getParentGridData() {
this.chartSvc.getAllSprints(this.loginUser.syndicateDetailId, this.projectId)
.subscribe((data: any) => {
this.childdata = [];
if (data && data.sprint) {
data.sprint.forEach((item) => {
item.childs.forEach((child) => {
child.queryId = child.parentSprintId;
this.childdata.push(child);
});
});
this.aSprints = data.sprint;
this.childGridDataBind();
}
});
}
childGridDataBind() {
this.childGrid = {
dataSource: this.childdata,
// id: "DestGrid",
queryString: "queryId",
allowPaging: false,
pageSettings: { pageSize: 6, pageCount: 5 },
load: function() {
this.registeredTemplate = {}; //set registertemplate value as empty in load event
},
columns: [
// {
// field: "parentItemId",
// headerText: "ID",
// isPrimaryKey: true,
// width: 120
// },
{
field: "itemNumber",
headerText: "ID",
isPrimaryKey: false,
width: 120
},
{
field: "itemName",
headerText: "Name",
textAlign: "left",
template:this.childtemplate,
// "
", // "",
width: 120
},
{
field: "nodeType",
headerText: "Node Type",
textAlign: "left",
width: 120
}
,
{
field: "itemSTartDate",
headerText: "Start Date",
textAlign: "left",
width: 120
},
{
field: "itemEndDate",
headerText: "End Date",
textAlign: "left",
width: 120
}
]
};
}
The link is NOT showing UP for some reason with ng-templateIt is NOT able to get reference to childtemplateTypeError: Cannot read property 'elementRef' of undefinedat SprintsComponent.push../src/app/project-charts/sprints/sprints.component.ts.SprintsComponent.ngAfterViewInit (sprints.component.ts:805)at callProviderLifecycles (core.js:21414)at callElementProvidersLifecycles (core.js:21388)at callLifecycleHooksChildrenFirst (core.js:21378)at checkAndUpdateView (core.js:29448)at callViewAction (core.js:29680)at execEmbeddedViewsAction (core.js:29643)at checkAndUpdateView (core.js:29440)at callViewAction (core.js:29680)at execComponentViewsAction (core.js:29622)<ng-template #childtemplate let-data><div><a rel='nofollow' rel='nofollow' href="https://ej2.syncfusion.com/documentation/grid/" (click)="hyperclick($event)">{{data.itemName}}a>div>ng-template>import { Component,TemplateRef, Inject, AfterViewInit, ViewContainerRef, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';import { EditSettingsModel, CellEditArgs, ToolbarItems, IEditCell, CommandModel, ContextMenuItemModel, FilterSettingsModel, SaveEventArgs, GridComponent, Column } from '@syncfusion/ej2-angular-grids';import { PageSettingsModel, CommandClickEventArgs } from '@syncfusion/ej2-angular-grids';import { ProjectChartsService } from '../project-charts.service';import { LeftNavService } from 'src/app/onboarding/left-nav.service';import { TabComponent } from '@syncfusion/ej2-angular-navigations';import { ClickEventArgs, EventArgs } from '@syncfusion/ej2-angular-navigations';import { DialogComponent } from '@syncfusion/ej2-angular-popups';import { EmitType } from '@syncfusion/ej2-base';import { GroupSettingsModel,parentsUntil,DetailRowService } from '@syncfusion/ej2-angular-grids';import { AnimationModel, RangeColorModel, ProgressBar } from '@syncfusion/ej2-progressbar';import { ProgressTheme, ILoadedEventArgs } from '@syncfusion/ej2-progressbar';import { FontModel } from '@syncfusion/ej2-angular-charts';import { Router } from '@angular/router';@Component({selector: 'app-sprints',templateUrl: './sprints.component.html',styleUrls: ['./sprints.component.css'],providers: [DetailRowService]})export class SprintsComponent implements OnInit, AfterViewInit {@ViewChild("grid", { static: false }) grid: GridComponent;@ViewChild('element', { static: true }) element;@ViewChild('tabsElement', { static: false }) tabInstance: TabComponent;@ViewChild('ejDialog', { static: false }) ejDialog: DialogComponent;@ViewChild('progress', { static: false }) public progress: ProgressBar;@ViewChild("childtemplate", { static: true }) public childtemplate: any;hyperclick(args) {console.log(this);console.log(args);}ngAfterViewInit() {this.childtemplate.elementRef.nativeElement._viewContainerRef = this.viewContainerRef;}getParentGridData() {this.chartSvc.getAllSprints(this.loginUser.syndicateDetailId, this.projectId).subscribe((data: any) => {this.childdata = [];if (data && data.sprint) {data.sprint.forEach((item) => {item.childs.forEach((child) => {child.queryId = child.parentSprintId;this.childdata.push(child);});});this.aSprints = data.sprint;this.childGridDataBind();}});}childGridDataBind() {this.childGrid = {dataSource: this.childdata,// id: "DestGrid",queryString: "queryId",allowPaging: false,pageSettings: { pageSize: 6, pageCount: 5 },load: function() {this.registeredTemplate = {}; //set registertemplate value as empty in load event},columns: [// {// field: "parentItemId",// headerText: "ID",// isPrimaryKey: true,// width: 120// },{field: "itemNumber",headerText: "ID",isPrimaryKey: false,width: 120},{field: "itemName",headerText: "Name",textAlign: "left",template:this.childtemplate,// "",// "",width: 120},{field: "nodeType",headerText: "Node Type",textAlign: "left",width: 120},{field: "itemSTartDate",headerText: "Start Date",textAlign: "left",width: 120},{field: "itemEndDate",headerText: "End Date",textAlign: "left",width: 120}]};}
Need help urgently
RS
Rajapandiyan Settu
Syncfusion Team
January 11, 2021 07:17 AM UTC
Hi Vin,
Thanks for your update.
We are tried to reproduce the reported behavior with the provided code example, but it was unsuccessful at our end. The hyperlink element in the childGrid is working fine when we rendering the childGrid by childGridDataBind() method. Find the below sample and code example for your reference.
|
[app.component.html]
// render the Grid using ng if condition
<ejs-grid *ngIf="childdatasuccess" #grid id="Grid" [dataSource]="parentData" [childGrid]="childGrid"
[allowPaging]="true">
<e-columns>
<e-column field="EmployeeID" headerText="Employee ID" width="120" textAlign="Right"></e-column>
<e-column field="FirstName" headerText="Name" width="140"></e-column>
<e-column field="Title" headerText="Title" width="170"></e-column>
</e-columns>
</ejs-grid>
// childTemplate1
<ng-template #childtemplate1 let-data>
<div>
<a rel='nofollow' href="https://ej2.syncfusion.com/documentation/grid/" (click)="hyperclick($event)">{{data.ShipCity}}</a>
</div>
</ng-template>
// childTemplate2
<ng-template #childtemplate2 let-data>
<div>
<a rel='nofollow' href="https://ej2.syncfusion.com/documentation/grid/" (click)="hyperclick($event)">{{data.ShipName}}</a>
</div>
</ng-template>
[app.component.ts]
export class AppComponent {
----
@ViewChild("grid", { static: true })
public grid: GridComponent;
@ViewChild("childtemplate1", { static: true })
public childtemplate1: any;
@ViewChild("childtemplate2", { static: true })
public childtemplate2: any;
public childdatasuccess: boolean = false;
----
ngOnInit(): void {
this.parentData = employeeData;
this.getParentGridData(); // call this method to get the data for child Grid
}
getParentGridData() {
let state = { skip: 0, take: 100 };
// execute the service
this.service.getData(state).subscribe((data: any) => {
this.childdata = [];
// get the child Grid data
this.childdata = data.result;
this.childGridDataBind(); // this method called to create the child Grid
});
}
ngAfterViewInit() {
this.childtemplate1.elementRef.nativeElement._viewContainerRef = this.viewContainerRef;
this.childtemplate2.elementRef.nativeElement._viewContainerRef = this.viewContainerRef;
}
hyperclick(args) {
console.log(this);
console.log(args);
}
childGridDataBind() {
// define the child Grid
this.childGrid = {
dataSource: orderDatas,
queryString: "EmployeeID",
allowPaging: true,
pageSettings: { pageSize: 6, pageCount: 5 },
load: function() {
this.registeredTemplate = {}; //set registertemplate value as empty in load event
},
columns: [
{
field: "OrderID",
headerText: "Order ID",
textAlign: "Right",
width: 120
},
{
field: "ShipCity",
headerText: "Ship City",
template: this.childtemplate1,
width: 120
},
{
field: "ShipName",
headerText: "Ship Name",
template: this.childtemplate2,
width: 150
}
]
};
this.childdatasuccess = true; // make the ngIf condition as true after defining the childGrid… now the Grid will be rendered
}
}
|
In the above code example, we rendered the Grid based on the *ngIf condition. In the childGridDataBind() method, we defined the childGrid for the Grid. After we defining the childGrid, we make the ngIf condition as true to render the Grid in DOM.
Note: There is some misalignment in Grid if we load the childGrid after the Grid rendered in DOM. So, we have used *ngIf to avoid this.
Still, If you face the same issue, please share the below details to validate further.
- Share the issue reproducible sample or make the issue in the given sample.
- When/Where did you call the getParentGridData() method in your application?
Regards,
Rajapandiyan S
VI
vin
January 12, 2021 03:24 AM UTC
If i changed the child datsource it didn't work with ur example
if you can help me with why elementRef is undefined?
TypeError: Cannot read property 'elementRef' of undefined
this.childGrid = {
dataSource: this.childdata,
VI
vin
January 13, 2021 04:03 AM UTC
I tried hard coding the data, still i get error
Cannot read property 'elementRef' of undefined
Cannot read property 'elementRef' of undefined
There is something missing in references i feel, need help with it.
I pasted all the Syncfusion components i used
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { SpreadsheetAllModule } from '@syncfusion/ej2-angular-spreadsheet';
import { SliderModule,TextBoxModule } from '@syncfusion/ej2-angular-inputs';
import { DropDownListModule } from '@syncfusion/ej2-angular-dropdowns';
import { GridModule,RowDDService , CommandColumnService, PagerModule, EditService, ToolbarService, ContextMenuService, PdfExportService, ExcelExportService } from '@syncfusion/ej2-angular-grids';
import { PageService, SortService, FilterService, GroupService } from '@syncfusion/ej2-angular-grids';
import { GridAllModule } from '@syncfusion/ej2-angular-grids';
import { ToastModule } from '@syncfusion/ej2-angular-notifications';
import { SwitchModule } from '@syncfusion/ej2-angular-buttons';
import { DialogModule } from '@syncfusion/ej2-angular-popups';
import { UploaderModule } from '@syncfusion/ej2-angular-inputs';
import { TabComponent, TabModule, AccordionModule } from '@syncfusion/ej2-angular-navigations';
import { ChartModule, AccumulationChartModule,RangeNavigatorAllModule } from '@syncfusion/ej2-angular-charts';
import { CategoryService, LineSeriesService } from '@syncfusion/ej2-angular-charts';
import { AccumulationChartAllModule, DataLabelService } from '@syncfusion/ej2-angular-charts';
import { DateRangePickerModule } from '@syncfusion/ej2-angular-calendars';
import { GanttAllModule } from '@syncfusion/ej2-angular-gantt';
import { SelectionService, ResizeService, ReorderService, DayMarkersService } from '@syncfusion/ej2-angular-gantt';
import { HeatMapModule } from '@syncfusion/ej2-angular-heatmap';
import { LegendService, AdaptorService, TooltipService} from '@syncfusion/ej2-angular-heatmap';
import { DiagramAllModule, SymbolPaletteAllModule, OverviewAllModule } from '@syncfusion/ej2-angular-diagrams';
import { HierarchicalTreeService, MindMapService, RadialTreeService, ComplexHierarchicalTreeService } from '@syncfusion/ej2-angular-diagrams';
import { DataBindingService, SnappingService, PrintAndExportService, BpmnDiagramsService} from '@syncfusion/ej2-angular-diagrams';
import { SymmetricLayoutService, ConnectorBridgingService, UndoRedoService, LayoutAnimationService} from '@syncfusion/ej2-angular-diagrams';
import { DiagramContextMenuService, ConnectorEditingService } from '@syncfusion/ej2-angular-diagrams';
import { MultiSelectModule } from '@syncfusion/ej2-angular-dropdowns';
import { CheckBoxModule, ButtonModule } from '@syncfusion/ej2-angular-buttons';
import { MultiSelectAllModule } from '@syncfusion/ej2-angular-dropdowns';
import { MomentModule } from 'ngx-moment';
import { CommonModule } from '@angular/common';
import { SidebarModule } from '@syncfusion/ej2-angular-navigations';
import { NumericTextBoxModule } from '@syncfusion/ej2-angular-inputs';
import { ContextMenuModule } from '@syncfusion/ej2-angular-navigations';
import { KanbanModule } from '@syncfusion/ej2-angular-kanban';
import { ProgressBarModule } from '@syncfusion/ej2-angular-progressbar';
RS
Rajapandiyan Settu
Syncfusion Team
January 13, 2021 11:49 AM UTC
Hi Vin,
Thanks for your update.
We have created a new incident under your Direct trac account to follow up with this query. We suggest you to follow up with the incident for further updates. Please log in using the below link.
Regards,
Rajapandiyan S
PC
pcafstockf
April 11, 2021 12:45 AM UTC
Hi Rajapandiyan,
I am seeing something very similar to this, and in my case it seems that angular lifecycle events are not being called.
Using the column template approach:
<e-column field="shippingDetails" headerText="Shipping">
<ng-template #template let-data>
<app-shipping-detail [details]="data.shippingDetails">app-shipping-detail>
ng-template>
e-column>
I find that the ShippingDetailComponent *constructor* is called, but all other Angular lifecycle methods ngOnInit, ngAfterViewInit, ngOnChanges etc., are never called.
You mentioned an issue filed to Vin's Direct Trac account, but could you update the rest of us as to whether that issue is related to the lifecycle methods not being called?
Thanks,
Earl
RS
Rajapandiyan Settu
Syncfusion Team
April 13, 2021 11:38 AM UTC
Hi Pcafstockf,
Thanks for contacting Syncfusion support.
We are tried to reproduce the reported behavior, but it was unsuccessful at our end. The child-component’s hooks are called properly when rendering it in the column template. Please find the sample for your reference.
Still, if you face the same issue please share the below details to replicate this at our end.
- Share the complete code you have used.
- Share the package.json file.
- If possible, share the simple issue reproducible sample or try to make the issue in given sample.
Regards,
Rajapandiyan S
Marked as answer
SIGN IN To post a reply.