Grid child

How do i adda link to child grid record

 

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. 
 
 
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. 
 
 
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> 
    <a rel='nofollow' href="https://ej2.syncfusion.com/documentation/grid/">{{data.ShipCity}}</a> 
  </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,TemplateRefInjectAfterViewInitViewContainerRefOnInitViewChildViewEncapsulation } from '@angular/core';
import { EditSettingsModelCellEditArgsToolbarItemsIEditCellCommandModelContextMenuItemModelFilterSettingsModelSaveEventArgsGridComponentColumn } from '@syncfusion/ej2-angular-grids';
import { PageSettingsModelCommandClickEventArgs } 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 { ClickEventArgsEventArgs } 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 { AnimationModelRangeColorModelProgressBar } from '@syncfusion/ej2-progressbar';
import { ProgressThemeILoadedEventArgs } 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 OnInitAfterViewInit {
  
  

  @ViewChild("grid", { static: false }) gridGridComponent;
  @ViewChild('element', { static: true }) element;
  @ViewChild('tabsElement', { static: false }) tabInstanceTabComponent;
  @ViewChild('ejDialog', { static: false }) ejDialogDialogComponent;
  @ViewChild('progress', { static: false }) public progressProgressBar;
  @ViewChild("childtemplate", { static: true })  public childtemplateany;

  hyperclick(args) { 
    console.log(this); 
    console.log(args); 
  } 

  ngAfterViewInit() {
    this.childtemplate.elementRef.nativeElement._viewContainerRef = this.viewContainerRef;
  }

getParentGridData() {
   
    this.chartSvc.getAllSprints(this.loginUser.syndicateDetailIdthis.projectId)
      .subscribe((dataany=> {
       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: 6pageCount: 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,
          //   " ${itemName}
",

          // "
 ${ShipName}
", 
          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
        }


      ]

    };
   
  }





VI vin replied to vin January 9, 2021 07:30 PM UTC

The link is NOT showing UP for some reason with ng-template


It is NOT able to get reference to childtemplate

TypeError: Cannot read property 'elementRef' of undefined
    at 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,TemplateRefInjectAfterViewInitViewContainerRefOnInitViewChildViewEncapsulation } from '@angular/core';
import { EditSettingsModelCellEditArgsToolbarItemsIEditCellCommandModelContextMenuItemModelFilterSettingsModelSaveEventArgsGridComponentColumn } from '@syncfusion/ej2-angular-grids';
import { PageSettingsModelCommandClickEventArgs } 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 { ClickEventArgsEventArgs } 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 { AnimationModelRangeColorModelProgressBar } from '@syncfusion/ej2-progressbar';
import { ProgressThemeILoadedEventArgs } 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 OnInitAfterViewInit {
  
  

  @ViewChild("grid", { static: false }) gridGridComponent;
  @ViewChild('element', { static: true }) element;
  @ViewChild('tabsElement', { static: false }) tabInstanceTabComponent;
  @ViewChild('ejDialog', { static: false }) ejDialogDialogComponent;
  @ViewChild('progress', { static: false }) public progressProgressBar;
  @ViewChild("childtemplate", { static: true })  public childtemplateany;

  hyperclick(args) { 
    console.log(this); 
    console.log(args); 
  } 

  ngAfterViewInit() {
    this.childtemplate.elementRef.nativeElement._viewContainerRef = this.viewContainerRef;
  }

getParentGridData() {
   
    this.chartSvc.getAllSprints(this.loginUser.syndicateDetailIdthis.projectId)
      .subscribe((dataany=> {
       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: 6pageCount: 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,
          //   " ${itemName}
",

          // "
 ${ShipName}
", 
          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. 
 
  1. Share the issue reproducible sample or make the issue in the given sample.
  2. 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
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 { FormsModuleReactiveFormsModule } 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 ,  CommandColumnServicePagerModuleEditServiceToolbarService,  ContextMenuService,  PdfExportServiceExcelExportService } from '@syncfusion/ej2-angular-grids';
import { PageServiceSortServiceFilterServiceGroupService } 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 { TabComponentTabModuleAccordionModule   } from '@syncfusion/ej2-angular-navigations';


import { ChartModuleAccumulationChartModule,RangeNavigatorAllModule } from '@syncfusion/ej2-angular-charts';
import { CategoryServiceLineSeriesService } from '@syncfusion/ej2-angular-charts';
import {  AccumulationChartAllModuleDataLabelService } from '@syncfusion/ej2-angular-charts';

import { DateRangePickerModule } from '@syncfusion/ej2-angular-calendars';

import {  GanttAllModule } from '@syncfusion/ej2-angular-gantt';
import {  SelectionServiceResizeService,  ReorderService,   DayMarkersService  } from '@syncfusion/ej2-angular-gantt';


import { HeatMapModule } from '@syncfusion/ej2-angular-heatmap';
import { LegendServiceAdaptorServiceTooltipServicefrom '@syncfusion/ej2-angular-heatmap'

import { DiagramAllModuleSymbolPaletteAllModuleOverviewAllModule } from '@syncfusion/ej2-angular-diagrams';

import { HierarchicalTreeServiceMindMapServiceRadialTreeServiceComplexHierarchicalTreeService } from '@syncfusion/ej2-angular-diagrams';
import { DataBindingServiceSnappingServicePrintAndExportServiceBpmnDiagramsServicefrom '@syncfusion/ej2-angular-diagrams';
import { SymmetricLayoutServiceConnectorBridgingServiceUndoRedoServiceLayoutAnimationServicefrom '@syncfusion/ej2-angular-diagrams';
import { DiagramContextMenuServiceConnectorEditingService } from '@syncfusion/ej2-angular-diagrams';

import { MultiSelectModule } from '@syncfusion/ej2-angular-dropdowns';
import { CheckBoxModuleButtonModule } 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. 
 
  1. Share the complete code you have used.
  2. Share the package.json file.
  3. If possible, share the simple issue reproducible sample or try to make the issue in given sample.
 
Regards, 
Rajapandiyan S 


Marked as answer
Loader.
Up arrow icon