4

Well, this is my parent component where I am trying to pass the template nodeTemplate to the child ils-tree

<div class="nodes-panel">
    <ils-tree layout="horizontal" [json]="nodes" [template]="nodeTemplate">
    </ils-tree>
</div>

<ng-template #nodeTemplate>
    <ng-template let-node  pTemplate="default">
        <p class="node-type">{{node.data.nodeType}}</p>
        <p class="node-name">{{node.data.name}}</p>
    </ng-template>
    <ng-template let-node  pTemplate="orgNode">
        <p class="org-node-name">{{node.data.name}}</p>
    </ng-template>
</ng-template>

The child component ils-tree's HTML looks this way

<p-tree
  [value]="nodes"
  [layout]="layout"
  selectionMode="single"
  [(selection)]="selectedNode"
  [loading]="loading"
>
  <ng-container *ngTemplateOutlet="template"></ng-container>
</p-tree>

and the controller file has

@Input()
template: TemplateRef<any>;

Basically, the ps are nowhere to be seen and yes, the data json is being passed successfully. Help!

P.S The template when embedded directly, in between, works. That is,

<p-tree
  [value]="nodes"
  [layout]="layout"
  selectionMode="single"
  [(selection)]="selectedNode"
  [loading]="loading"
>
  <ng-template let-node  pTemplate="default">
        <p class="node-type">{{node.data.nodeType}}</p>
        <p class="node-name">{{node.data.name}}</p>
    </ng-template>
    <ng-template let-node  pTemplate="orgNode">
        <p class="org-node-name">{{node.data.name}}</p>
    </ng-template>
</p-tree>
halfer
  • 19,824
  • 17
  • 99
  • 186
Aakash Verma
  • 3,705
  • 5
  • 29
  • 66
  • I never used TemplateRef's but when I read this blog https://blog.mgechev.com/2017/10/01/angular-template-ref-dynamic-scoping-custom-templates/" I don't think Input-decorator ist correct here. – MoxxiManagarm Mar 29 '19 at 08:35
  • 1
    I'm having the same issue while trying to extend the PrimeNg MultiSelect. But instead of using 2 nested ng-templates like you did, I'm using only the inner ng-template, nested inside my custom component, and using `@ContentChild` to access it. The problem I have is that the template is loaded fine, but I cannot get the context to see the data. – AsGoodAsItGets Mar 29 '19 at 11:51
  • Let me try that. Thanks AsGoodAsItGets – Aakash Verma Mar 30 '19 at 05:57
  • Didn't work @AsGoodAsItGets – Aakash Verma Mar 30 '19 at 11:59
  • Unfortunately, I do not have a solution for your problem - but I can tell you why this is happening. `ng-template` are not rendered by Angular, nor should they be - the expectation is that these will be explicitly rendered somewhere else. So, when you use `ng-container *ngTemplateOutlet` you're asking Angular to render everything inside that template - which ends up being "nothing" because `ng-template`s are not rendered. You also cannot use `ng-content` to pass templates for the same reason. – Vlad274 Apr 02 '19 at 04:05
  • In your situation, I'd probably create multiple ChildComponents and declare the `ng-templates` in-line. Alternatively, I'd try to move the `p-tree` component into the `ng-template` that I pass to the ChildComponent. I _think_ either solution will work – Vlad274 Apr 02 '19 at 04:07

1 Answers1

1

I think primeng tree doesn't let you use a template inside another templates with the pTemplate correct.

I could make a workaround declaring the templates separated and passing the type too. The main page would look like:

<ils-tree [templates]="[{type:'orgNode',template:templateOrg},
{type:'default',template:templateDefault}]"
 [data]="data"></ils-tree>

<ng-template let-node="node" pTemplate="default" #templateDefault>
    <p class="node-type">{{node.label}}</p>
</ng-template>

<ng-template let-node="node" pTemplate="orgNode" #templateOrg>
    <p class="org-node-name">{{node.label}}</p>
</ng-template>

Then the ils-tree.html would look like:

<p-tree [value]="data">
    <ng-container *ngFor="let temp of templates">
    <ng-template [pTemplate]="temp.type" let-node>
        <ng-template [ngTemplateOutlet]="temp.template" [ngTemplateOutletContext]="{
                 node:node
               }">
            </ng-template>
        </ng-template>
    </ng-container>
</p-tree>

The trick here is passing the node you are using as a context with ngTemplateOutletContext to your template so you can use it in the main with the let-node="node".

The ils-tree.ts would look like:

  @Input() templates: any[];
  @Input() data: any;

In my example I added a model for the templates to make it more easy to read.

You have the live example here:
https://stackblitz.com/edit/angular-tree-templates

Daniel Piñeiro
  • 3,009
  • 1
  • 16
  • 26