developer033
developer033

Reputation: 24874

Angular 1.5.x - Issue with nested components

First of all, I'm using components.

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 illustrate better the situation

Can you explain to me how I can make it work?

Upvotes: 0

Views: 747

Answers (2)

gyc
gyc

Reputation: 4360

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);
}

Upvotes: 1

Artem K.
Artem K.

Reputation: 804

Your child should take the item as input via bindings.

(function() {
  'use strict';

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

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

  }
})();

So your parent template will look like

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

The rest should work same.

Upvotes: 0

Related Questions