Josh
Josh

Reputation: 1281

ngForTemplate - use template via ContentChild, or fall back to default

Using Angular 4.0.3

I'm trying to create a component to display an array as a list. I need to have the option of passing a template to this component. If a template is passed, the list will be rendered using it. Otherwise, an embedded template should be used to render.

I've found a Plunkr that partially solves what I'm trying to do - it shows how to pass a template to a component, and have the component render using it. It can be found here: https://embed.plnkr.co/ollxzUhka77wIXrJGA9t/

I've forked it and tried adding the default template functionality required. To do this, I've:

That plunkr can be found at https://embed.plnkr.co/QtMk3h/

When running, I'm getting this exception:

Error in ./DynamicListComponent class DynamicListComponent - inline template:0:29

I'm not sure what I'm doing wrong, as setting *ngForTemplate="itemTemplate" works, but neither *ngForTemplate="defaultItemTemplate" or *ngForTemplate="itemTemplate || defaultItemTemplate" don't.

What am I doing wrong?

I also notice that *ngFor is deprecated, so maybe I'm approaching this in the wrong way now?

Upvotes: 2

Views: 1538

Answers (1)

Julia Passynkova
Julia Passynkova

Reputation: 17859

I rewrite this plnkr using Angular4 + added else clause.

https://plnkr.co/edit/i3czMfuziB9eWkiepEW0?p=preview

  @Component({
    selector: 'dynamic-list',
    template: `<div *ngFor="let item of items">
         <ng-container *ngIf="itemTemplate;else elseBlock">
            <ng-container *ngTemplateOutlet="itemTemplate; context: {\$implicit:item}"></ng-container>
         </ng-container>
    </div>

    <ng-template #elseBlock>else</ng-template>
    `
  })
  export class DynamicListComponent {

    @ContentChild(TemplateRef)
    public itemTemplate: TemplateRef;

    @Input()
    public items: number[];

    ngAfterContentInit() {
      console.log(this.itemTemplate);
    }
  }


  @Component({
    selector: 'dynamic-list-item',
    template: `<div>
          Template Item #:{{item}}
  </div>`
  })
  export class DynamicListItemTemplateComponent {
    @Input() public item: number;
  }

  @Component({
    selector: 'my-app',
    providers: [],
    template:`
  <h3>Inline</h3>

  <h3>Default</h3>
  <dynamic-list [items]="items">
  </dynamic-list>

  <h3>Not Default</h3>
  <div  *ngFor="let item of items">
    <div>
    Inline template item #: {{item}}
    </div>
  </div>


  <h3>List component with inline template</h3>
  <dynamic-list [items]="items">
    <ng-template let-item>
        Inline template item #: {{item}}
    </ng-template>
  </dynamic-list> 


  <h3>List component with component template</h3>
  <dynamic-list [items]="items">
    <dynamic-list-item template="let item" [item]="item"></dynamic-list-item>
  </dynamic-list> 

    `,
  })
  export class App {
    private items = [1, 2, 3, 4];
  }

Upvotes: 2

Related Questions