Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 passing html to ng-content with bindings

I'm writing angular components for the foundation css framework. I am working on the tabs component, and want to be able to pass some HTML to the <ng-content> of this.

The problem is, I also need to pass html which a user can put bindings on, like this:

PARENT TEMPLATE

<tabs [data]='example'>     <div> Age <br> {{item.age}} </div>` </tabs> 

TABS COMPONENT

<ul class="tabs" #tabs>   <li *ngFor="let item of data | async" (click)="tabClick($event)">       <a>{{item.name}}</a>   </li> </ul> <div>   <ng-content></ng-content> </div> 

TABS TYPESCRIPT

@Component({   selector: 'tabs',   templateUrl: './tabs.component.html' })  export class TabsComponent {   @Input('data') data:any;   @ViewChild('tabs') tabs: ElementRef; } 

Where item is a reference to an object in the example array.

However, I get this error: Cannot read property 'name' of undefined as item is being evaluated before it is inserted into the <ng-content> directive.

Is there a way to get around this limitation, or am I going about this the wrong way?

like image 500
userqwert Avatar asked Mar 18 '17 18:03

userqwert


People also ask

How does Angular component pass custom content?

The first step to passing data into an Angular component is to create a custom property to bind to. This is done via “input” binding to pass data from one component to another (typically parent to child). This custom input binding is created via the @Input() decorator!

How do I display HTML inside an Angular binding?

To add HTML that contains Angular-specific markup (property or value binding, components, directives, pipes, ...) it is required to add the dynamic module and compile components at runtime.

What is Contentprojection?

Content projection is a pattern in which you insert, or project, the content you want to use inside another component. For example, you could have a Card component that accepts content provided by another component.


1 Answers

update Angular 5

ngOutletContext was renamed to ngTemplateOutletContext

See also https://github.com/angular/angular/blob/master/CHANGELOG.md#500-beta5-2017-08-29

original

ngTemplateOutlet or ngForTemplate can be used for that use case:

<tabs [data]='example'>   <ng-template let-item>     <div> Age <br> {{item.age}} </div>`   </ng-template> </tabs> 
@Component({   ...   template: `     <ul class="tabs" #tabs>       <li *ngFor="let item of data | async" (click)="tabClick($event)">           <a>{{item.name}}</a>       </li>     </ul>     <div>       <ng-template [ngTemplateOutlet]="templateRef" [ngTemplateOutletContext]="{$implicit: (data | async)}"></ng-template>     </div>   ` }) class TabsComponent {   @ContentChild(TemplateRef) templateRef:TemplateRef; } 

See also Angular 2 bind transcluded content to loop variable

like image 116
Günter Zöchbauer Avatar answered Oct 08 '22 21:10

Günter Zöchbauer