Reputation: 23
How can you pass an action from a parent view/component to a child component and still maintain the context of the parent. The problem shown in the below plunkr shows that if the action is executed in the component it is in the context of the component and not the parent who passed the action. Basically the typical "that = this" issue.
Yes you can use eventAggregator to do this, but how would you without it. Would you have to pass the whole viewModel into the component?
http://plnkr.co/edit/n1xPUdR5nhXwwIivawBj?p=preview
// app.js
import { inject } from 'aurelia-framework';
import { MyService } from './my-service';
@inject(MyService)
export class App {
constructor(myService) {
this.myService = myService;
this.message = "Hello World!";
}
doThing() {
console.log('do a thing');
this.myService.foo();
}
}
<!--app.html-->
<template>
<require from="./my-component"></require>
<p>${message}</p>
<button click.delegate="doThing()">Do the thing - in app.html</button>
<my-component do.bind="doThing"></my-component>
</template>
// my-component.js
import { bindable } from 'aurelia-framework';
@bindable('do')
export class MyComponentCustomElement {
}
<!-- my-component.html -->
<template>
<button click.delegate="do()">Do the thing - in my-component</button>
</template>
// my-service.js
export class MyService {
foo() {
alert("pity da foo");
}
}
Upvotes: 2
Views: 4276
Reputation: 1398
If you REALLY wanted to do this (there may be cleaner ways to go about it), you would need to get access to your parent's view-model from your child view-model and then, when calling the method in your child view's click binding, use .call()
to change the scope/context of the do()
method when it's called.
So in your child view-model, first gain access to your parent's view-model by adding the following bind
method:
bind( bindingContext ) {
// bindingContext is your parent view-model
this.parent = bindingContext;
}
After you have access to your parent view-model you can update the click binding in your child view to be as follows:
<button click.delegate="do.call( parent )">Do the thing - in my-component</button>
This will call the do()
method from the parent view-model's context.
You can use either .call( scope/context, list, of, args, ... )
or .apply( scope/context, [array of args])
. For more info on the .call()
method check out Mozilla's explanation
Upvotes: 6