developer033 developer033 - 3 months ago 311
AngularJS Question

Angular 1.5.x - Issue with nested components

First of all, I'm using

.

I have this "parent"
component
:

(function() {
'use strict';

angular
.module('parentModule', [])
.component('parent', {
templateUrl: 'parent.tpl.html',
controller: ParentCtrl,
transclude: true,
bindings: {
item: '='
}
});

function ParentCtrl() {
var vm = this;
vm.item = {
'id': 1,
'name': 'test'
};
}
})();


And I'm simply trying to share the
object
item with another component, like this:

(function() {
'use strict';

angular
.module('childModule', [])
.component('child', {
templateUrl: 'child.tpl.html',
controller: ChildCtrl,
require: {
parent: '^item'
}
});

function ChildCtrl() {
console.log(this.parent)
var vm = this;

}
})();


View (Parent):

Parent Component:

<h1 ng-bind='$ctrl.item.name'></h1>
<child></child>


View (Child):

Child component:

Here I want to print the test that is in the parent component
<h2 ng-bind='$ctrl.item.name'></h2>


Actually I'm getting the following error:


Expression 'undefined' in attribute 'item' used with directive
'parent' is non-assignable!


Here's the DEMO to ilustrate better the situation

Can you explain me how can I make it work?

gyc gyc
Answer

You need to remove the bindings from yor parent component. bindings binds to the component controller like scope binds to a directive's scope. You're not passing anything to <parent></parent> So you have to remove it.

Then your child component requires a parent component, not an item. So

  require: {
    parent: '^parent'
  }

Of course the child template should be modified to:

<h2 ng-bind='$ctrl.parent.item.name'></h2>

Finally, if from the child controller you want to log the item that is inside the parent, you will have to write:

  function ChildCtrl($timeout) {
    var vm = this;
    $timeout(function() {
      console.log(vm.parent.item);
    });
  }

I never need the timeout in my components, so there might be something obvious that I missed.

http://plnkr.co/edit/0DRlbedeXN1Z5ZL45Ysf?p=preview

EDIT:

Oh I forgot, you need to use the $onInit hook:

this.$onInit = function() {
  console.log(vm.parent.item);
}