0

You can see full proof of concept here: https://plnkr.co/edit/slshjP?p=preview

I want to create a simple tree component, that allows the user to specify template for each node eg.

<app-tree-editor [nodes]="fields">
  <ng-template treeTemplate let-node>{{node}}</ng-template>
</app-tree-editor>

I define a directive to get hold of the template:

@Directive({
  selector: '[treeTemplate]',
})
export class TreeEditorTemplate {
  constructor(public template: TemplateRef<{}>) {

  } 
}

And then inside of my tree I get a reference to it.

@Component({
  selector: 'app-tree-editor',
  template: `
    <app-tree-node [node]="root" [templateRef]="nodeTemplateRef">
    </app-tree-node>
  `,
})
export class TreeEditorComponent {
  @Input() nodes: any;

  @ContentChild(TreeEditorTemplate) nodeTemplate: TreeEditorTemplate;
  nodeTemplateRef: TemplateRef<{}>;

  root: any;

  ngOnInit() {
    this.root = {children: this.nodes};
  }

  ngAfterContentInit(): void {
    this.nodeTemplateRef = this.nodeTemplate.template;
  }
}

The problem is, the template I get is a comment node :/

Any idea what I'm doing wrong?

Code with repro case: You can see full proof of concept here: https://plnkr.co/edit/slshjP?p=preview

2 Answers 2

1

You forgot to pass template ref to your child app-tree-node components:

app/tree-children.ts

@Component({
  selector: 'app-tree-children',
  template: `
  <div class='tree-indent'>
  <app-tree-node *ngFor="let child of nodes" [node]="child" 
                            [templateRef]="templateRef"></app-tree-node>
                              ^^^^^^^^^^^^^^^^^^^^^^
                                   add this
  </div>
  `
})
export class TreeChildrenComponent {
  nodes: any;

  templateRef: TemplateRef<any>;  <== add this
}

app/tree-node.ts

let componentRef = viewContainerRef.createComponent(componentFactory);
componentRef.instance.nodes = this.node.children || [];
componentRef.instance.templateRef = this.templateRef;   <== add this

Plunker Example

Sign up to request clarification or add additional context in comments.

Comments

0

You can use a template variable in this case and then pass it to the component through the @Input decorator.

<app-tree-editor [template]="template" [nodes]="fields">
    <ng-template #template let-node>{{node}}</ng-template>
</app-tree-editor>

And in your component you'd add the Input:

@Input() template: TemplateRef<any>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.