realist
realist

Reputation: 2385

Passing data from ngContent in angular

I want to create childComponent which generate datagrid. So, I create grid.component.html and grid.component.ts. My aim is, my team mate never touch grid.ts and grid.html. Because my grid structure will be similar in for all page in my app. So, they only add like myComponent.html and myComponent.ts. They will write button's html and button's click event to myComponent. I can create grid. But my problem is, I can't access rowData in showDetail method. ("rowData" is implicit of primeNg directive. I wasn't setting anywhere. I only gave p-table value.)

myComponent.html

<app-grid>
  <ng-template pTemplate="body" let-rowData="rawData">
        <button label="Reject" (click)="reject(rowData)"></button>
        <button label="Detail" (click)="showDetail(rowData)"></button>
  </ng-template>
</app-grid>

myComponent.ts

reject(data){
  console.log("Reject data ", data);
}

showDetail(data){
   console.log("showDetail data ", data);
}

grid.component.ts

rawData = {}

@ContentChild(TemplateRef)
templateRef : TemplateRef<any>;

grid.component.html

<p-table [value]="globalVariables.myData">
   <ng-template pTemplate="body" let-rowData>  // This rowData come from PrimeNg "implicit" value
     <tr>
       <td *ngFor="let col of globalVariables.columns">
          {{ rowData[col.field] }}
       </td>
       <td>
         <ng-template *ngTemplateOutlet="templateRef; context : {rawData : rawData}"></ng-template>
       </td>
     </tr>
   </ng-template>
</p-table>

Upvotes: 2

Views: 6900

Answers (2)

Sunil
Sunil

Reputation: 11241

What you are looking for is dynamic html template which can act as the part parent component app-grid. So you should use <ng-template> instead of <ng-content>.

you app-grid will be as

grid.component.html

<table>
    <tr>
      <td>
        <ng-template 
     *ngTemplateOutlet="templateRef; context : {rawData : rawData, reject : reject, showDetail : showDetail}"
     >
     </ng-template>
      </td>
    </tr>
</table>

grid.component.ts

import { Component, OnInit, Input, TemplateRef, ContentChild } from '@angular/core';

@Component({
  selector: 'app-grid',
  templateUrl: './grid.component.html',
  styleUrls: ['./grid.component.css']
})
export class GridComponent implements OnInit {

  constructor() { }

  rawData = { content : " some content here"}

  @ContentChild(TemplateRef)
  templateRef : TemplateRef<any>;

  ngOnInit() {
  }

  reject(data){
    console.log("Reject data ", data);
  }

  showDetail(data){
     console.log("showDetail data ", data);
  }

}

Use component grid

<app-grid>
  <ng-template let-rowData="rawData" let-reject="reject" let-showDetail="showDetail">
    <button label="Reject" (click)="reject(rowData)">Reject</button>
    <button label="Detail" (click)="showDetail(rowData)">Show Details</button>
  </ng-template>
</app-grid>

You can see the working copy here - https://stackblitz.com/edit/angular-g15twn

Upvotes: 8

ランス
ランス

Reputation: 550

Use the @Input in the child component

<ng-content [rowData] = 'rowData' ></ng-content>

myComponent.ts

@Input rowData: any;

Upvotes: -3

Related Questions