Reputation: 3129
I am having trouble making the item looped from an ng-repeat from a parent component available to the scope of a nested component. The parent component is a carousel which contains many item components. The carousel is populated by the ng-repeat. I want to be able to access the "item" and a method of the carousel controller ("cr") in the item controller ("it"). I guess I am going about this in the totally wrong way. Appreciate if anyone can give me a steer.
carousel.component.html
<slick <!--slick attributes--> >
<div ng-repeat="item in cr.items">
<item-component></item-component>
</div>
</slick>
carousel.component.js
class CarouselController{
constructor(/*stuff*/){
'ngInject';
this.items =[
{"something":"The thing 1","otherthing":"The other thing 1"},
{"something":"The thing 2","otherthing":"The other thing 2"},
{"something":"The thing 3","otherthing":"The other thing 3"}
];
}
parentFunctionToCall(item){
console.log('I called a function on the parent!',item)
}
/*other stuff*/
}
export const CarouselComponent = {
templateUrl: './views/app/components/carousel/carousel.component.html',
controller: CarouselController,
controllerAs: 'cr',
bindings: {
}
}
item.component.html
<div data-something="{{item.something}}">
Yo,{{item.otherthing}}!
</div>
<a href="#" ng-click="cr.parentFunctionToCall(item)">
Trying to call a function on the parent component
</a>
item.component.js
class ItemController{
constructor($scope,/*stuff*/){
'ngInject';
//$scope.it.item & $scope.it.cr are both undefined
console.log(this);
//I understand this is the incorrect way but it works
this.$scope.item = this.$scope.$parent.item;
console.log(this);
}
/*other stuff*/
}
export const ItemComponent = {
templateUrl: './views/app/components/carousel/item.component.html',
controller: ItemController,
controllerAs: 'it',
bindings: {
"item":"=",//i can see this as undefined $scope in ItemController
"cr":"=" //i want to access a method on the parent controller
}
}
This shows whats up... https://plnkr.co/edit/UG20EtI4KxnVnTe8zzz4?p=preview
Upvotes: 1
Views: 372
Reputation: 3129
Frustratingly simple in the end.. I am not sure why this isnt made clearer in the documentation but its as easy as setting an attribute on the child component:
<slick <!--slick attributes--> >
<div ng-repeat="item in cr.items">
<!--new item="item" attr-->
<item-component item="item" call-parent="cr.parentFunctionToCall(item)"></item-component>
</div>
</slick>
Then the binding works as expected. Accessing a function on the parent behaves a similar way. Some event name needs to be added as an attribute (call-parent
but this can be anything). The binding needs to be added to the child component (as in @kuhnroyals comment):
...
bindings: {
item:"=",
callParent: '&'
}
And some interaction event on the child component eg ng-click="it.callParent()"
Working example here: https://plnkr.co/edit/RIOPs6?p=preview
Upvotes: 0
Reputation: 7563
Using controllerAs
you don't have a $scope
, you need to use this
. Especially with components.
this.items =[
{"something":"The thing 1","otherthing","The other thing 1"},
{"something":"The thing 2","otherthing","The other thing 2"},
{"something":"The thing 3","otherthing","The other thing 3"}
];
See https://docs.angularjs.org/guide/component
Upvotes: 1