9

I need to pass an expression to a component that will be evaluated inside an component's template.

For example, component:

@Component({
  selector: 'app-my-component',
  ...
})
export class MyComponent {
  @Input items: MyClass;
  @Input expression: String;
  ...
}

with component's template:

<div *ngFor="let item of items">
  {{expression}}
</div>

Usage of MyComponent:

<app-my-component [items]="listOfItems" [expression]="'[item.id] item.name'">
</app-my-component>

As there will be more than one input, I would like to avoid usage of TemplateRef.

Marin Relatic
  • 238
  • 2
  • 9
  • 1
    What is `'[item.id] item.name'` supposed to do? That doesn't look like an expression to me. You can't pass bindings around. – Günter Zöchbauer Oct 11 '16 at 09:24
  • pass it as `[expression]=" '{"id":[item.id],"name": item.name}' "` and use as expression.id and expression.name – Atal Kishore Oct 11 '16 at 09:49
  • @GünterZöchbauer this should evaluate to string, for item = {"id": 1, "name" : "Item1"} to [1] Item1 – Marin Relatic Oct 11 '16 at 10:44
  • @AtalKishore I need input 'expression' to be generic, so in MyComponent's view I can just pass it as an expression to be evaluated or as a template, without knowing it's structure – Marin Relatic Oct 11 '16 at 10:45
  • then use `[expression]=" '[' + item.id + '] ' + item.name "` – Atal Kishore Oct 11 '16 at 10:48
  • @MarinRelatic I don't can't make sense of your comment about "should evaluat to string". Can you please elaborate a bit more (please edit the question and add it here) – Günter Zöchbauer Oct 11 '16 at 10:48
  • I don't get what the `[` in the expression is supposed to do. Do you want to pass an array? What should the expression express? – Günter Zöchbauer Oct 11 '16 at 10:49
  • @GünterZöchbauer maybe it is not clear since I am using word 'expression'... This should be string format. So if string format '[item.id] item.name' is passed, it should write '[1] Item1'. Is there a way to make this work in Angular2? – Marin Relatic Oct 11 '16 at 11:03
  • What's the problem with Atals suggestion? – Günter Zöchbauer Oct 11 '16 at 11:04
  • @AtalKishore I can not do it that way since variable item is undefined in parent component, it gets defined only in MyComponent's view – Marin Relatic Oct 11 '16 at 11:05

1 Answers1

20

Maybe one of this options can helps you:

1) Using ngForTemplate input property of NgFor directive:

Component

@Component({
  selector: 'app-my-component',
  template: `
  <div *ngFor="let item of items template: itemTemplate"></div>`
})
export class MyComponent {
  @Input() items: any;
  @ContentChild(TemplateRef) itemTemplate: TemplateRef<any>;
}

Parent

<app-my-component [items]="listOfItems">
  <ng-template let-item>[{{item.id}}] {{item.name}}</ng-template>
</app-my-component>

Plunker

2) Using the NgTemplateOutlet directive

Component

@Component({
  selector: 'app-my-component',
  template: `
  <div *ngFor="let item of items">
    <ng-template [ngTemplateOutlet]="itemTemplate" [ngTemplateOutletContext]="{ $implicit: item }"></ng-template>
  </div>`
})
export class MyComponent {
  @Input() items: any;
  @ContentChild(TemplateRef) itemTemplate: TemplateRef<any>;
}

Parent remains the same:

<app-my-component [items]="listOfItems">
  <ng-template let-item>[{{item.id}}] {{item.name}}</ng-template>
</app-my-component>

Plunker

This way inside of <ng-template let-item>...</ng-template> you can use desired expression

yurzui
  • 205,937
  • 32
  • 433
  • 399
  • The first one doesn't seem to work anymore. Other than the change to `ng-template` I can't figure out why its is not working for me. It gives me no items, but does error when I use the wrong `let-*` property... – TrySpace Oct 19 '17 at 03:20