Join the Stack Overflow Community
Stack Overflow is a community of 6.5 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

My use case requires me to add several copies of a child component to a template programmatically (think: iterating through an array with *ngFor="let childComponent of componentArray"). The children components all emit a select event; the twist is that each of these components has a different event handler within the parent component. Trying to be clever, I decided to store the event handler as a property of each member of componentArray. So my template is now something like:

<my-cmp *ngFor="let childComponent of componentArray" (select)="childComponent.callback()"></my-cmp>

My model contains:

componentArray = [{data:0, callback:this.onSelect0}, {data:1, callback:this.onSelect1}];

onSelect0(){/*do stuff specific to childComponent 0*/}
onSelect1(){/*do stuff specific to childComponent 1*/}

callback is a reference to the class method I would like that particular childComponent's select event to trigger. callback is triggered properly; the problem is that from it I cannot access the rest of my component because this in that context refers to the component during that iteration of the loop.

It sounds more confusing than it is. I've found a workaround but it seems really clunky (I store the class instance as a property in each member of componentArray). I've made a plunkr accessible from http://plnkr.co/edit/VxxCR8hjUsxQ3SABWe8E?p=preview. Basically my question is: if I pass the event handler as an object property (childComponent.callback above), how can I access my class instance? Any feedback is welcome.

share|improve this question
up vote 3 down vote accepted

That's default JS/TS behavior if you pass a method reference directly. You can either use bind like methodName.bind(this) or a fat arrow function like () => methodName() to retain the scope of this.

In your Plunker just change this line

  private thing = {name:'ThingOne', onSelect: this.handlerOne };

to

  private thing = {name:'ThingOne', onSelect:() => this.handlerOne() };

Plunker example

share|improve this answer
    
Awesome; setting the onSelect property of thing to both onSelect:this.handlerOne.bind(this) and onSelect:()=>this.handlerOne() worked. Do you prefer one way over the other? – BeetleJuice May 20 at 23:03
    
Definitely ()=> everywhere – Günter Zöchbauer May 21 at 6:05

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.