Binding events when using a ngForTemplate in Angular 2 -
let's i've got simple list rendering component:
import {input, component } 'angular2/core' @component({ selector: 'my-list', template: ` <div *ngfor='#item of items' (click)='onitemclicked(item)'> {{item}} </div> ` }) class mylist { @input() items: string[]; onitemclicked(item) { console.log('item clicked:', item); } }
i use this:
<my-list [items]='myappsitems'></my-list>
so far good.
next decide want user able supply own template rendered items, change component
@component({ selector: 'my-list', template: ` <template ngfor [ngforof]="items" [ngfortemplate]="useritemtemplate" (click)='onitemclicked(item)'> </template> ` }) class mylist { @input() items: string[]; @contentchild(templateref) useritemtemplate: templateref; onitemclicked(item) { console.log('item clicked:', item); } }
and use this:
<my-list [items]='items'> <template #item> <h1>item: {{item}}</h1> </template> </my-list>
this works don't bind event handlers list items (plunker). if try bind click event, did in first version of component, angular throws following exception:
"event binding click not emitted directive on embedded template"
here's plunker showing that. can delete click binding , it'll work.
how fix this? want user able specify template subordinate item i'm going iterate via ngfor, need able bind handlers items.
item template defined in app context, not clear how attach my-list component context. have create wrapper directive handles template , variables, directive wrapped div capture events. can used this:
@directive({ selector: '[ngwrapper]' }) export class ngwrapper { @input() private item:any; private _viewcontainer:viewcontainerref; constructor(_viewcontainer:viewcontainerref) { this._viewcontainer = _viewcontainer; } @input() public set ngwrapper(templateref:templateref) { var embeddedviewref = this._viewcontainer.createembeddedview(templateref); embeddedviewref.setlocal('item', this.item) } }
@component({ selector: 'my-list', directives: [ngwrapper], template: ` <template ngfor #item [ngforof]="items"> <div (click)="onitemclicked(item)"> <template [ngwrapper]="useritemtemplate" [item]="item"></template> </div> </template> ` }) class mylist { @input() items: string[]; @contentchild(templateref) useritemtemplate: templateref; useritemtemplate1: templateref; onitemclicked(item) { console.log('item click:', item); } ngafterviewinit(){ this.useritemtemplate; } }
@component({ selector: 'my-app', directives: [mylist], template: ` <my-list [items]='items'> <template #item="item"> <h1>item: {{item}}</h1> </template> </my-list> ` }) export class app { items = ['this','is','a','test'] onitemclicked(item) { console.log('item click:', item); } }
the solution not prerfect good, check plunkr.
Comments
Post a Comment