Angular 1.5 Nested Component Bind parent Value

Problem

I am new to angularjs. I am trying angular 1.5 nested component. Can I bind parent component property in child component.

Ex:

<div ng-app='cbsApp' ng-controller='cbsCnt as ct'>
    <cbs-cus-comp com-bind='ct.name'>
        <child child-com-bind='cbsCusCompCntAs.name'></child>
    </cbs-cus-comp>
</div>

I can get ct.name value in com-bind. But can't get cbsCusCompCntAs.name in child-com-bind. (cbsCusCompCntAs is cbs-cus-comp controller)

Working Plunker : https://plnkr.co/edit/axQwTn?p=preview

Thanks in advance.

Problem courtesy of: Siva

Solution

In your first case you are referring directly to the controller scope via controllerAs.

When using components in angular 1.5 you can get hold of your parent component via require which will make parent's properties available after $onInit as per Components Documentation:

Note that the required controllers will not be available during the instantiation of the controller, but they are guaranteed to be available just before the $onInit method is executed!

In your specific case you can update the child component to require the parent:

var child = {
    require     :  {parentComp:'^cbsCusComp'},
    template    :  'Child : <b{{cbsCusChildCompCntAs.childComBind}}</b>',
    controller  :  cbsCusChildCompCnt,
    controllerAs:  'cbsCusChildCompCntAs'
    };

and its controller to get the data you need (I used the same names as you just to see it work):

function cbsCusChildCompCnt(){
  this.$onInit = function() {
    this.childComBind = this.parentComp.name;
  };
}

Updated plunker is here.

Solution courtesy of: bosch

Discussion

Although using the "require" parameter works, it creates a tightly bound relationship between the component acting as a child, which uses the "require" parameter, and the component acting as a parent, which consumes the child functionality.

A better solution is to use component communication as shown here.

Basically, you define a binding function in the child component definition, like so,

angular.module('app').component('componentName', {
templateUrl: 'my-template.html',
bindings: {
       myFunction: '&'
},
controller: function() { // Do something here}
});

Then, in the parent markup you provide a function to call,

Parent HTML

<user-list select-user="$ctrl.selectUser(user)">
</user-list>

Finally, in the parent controller, provide an implementation of the selectUser function.

Here's a working Plunk.

Discussion courtesy of: Latin Warrior

Wow... what a wonderful example... Took me a while to analyse it... so, I wrote my own (I think a bit more readable) version. I really do not know how to work with Plunker... so here's the code... Extract from my index.html file

<div ng-controller='appCtrl as ctrl'>
    <parent bind-id='ctrl.name'>
        <child bind-toid='parentCtrlAs.name'></child>
    </parent>
</div>

The .js file

(function () {
'use strict';

var 
    parentComponent =   
    {
        bindings    :   
        {
            bindId:'='
        },
        controller  : parentCtrl,
        controllerAs: 'parentCtrlAs',
        restrict    : 'A',
        transclude  : true,
        templateUrl : 'parent.html',
    };

var 
    childComponent =    
    {
        controller  : childCtrl,
        controllerAs: 'childCtrlAs',
        restrict    : 'A',
        require     :
        {
            myParent    :'^parent'
        },
        templateUrl :   'child.html',
};


angular
    .module('app', [])
    .controller('appCtrl'   , appCtrl)
    .component('parent'     , parentComponent)
    .component('child'      , childComponent);


function appCtrl(){
    this.name = 'Main..';
}

function childCtrl(){
    this.$onInit = function() {
        this.bindToid = this.myParent.name;
    };
}

function parentCtrl(){
    this.name   =   'Parent Component';
}

})();

Hope it helps, Regards, Johnny

Discussion courtesy of: Johnny Driesen

This recipe can be found in it's original form on Stack Over Flow.