Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 1.5 Nested Component Bind parent Value

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.

like image 449
Siva Avatar asked Mar 17 '16 06:03

Siva


3 Answers

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.

like image 57
bosch Avatar answered Oct 30 '22 01:10

bosch


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

like image 43
Johnny Driesen Avatar answered Oct 30 '22 01:10

Johnny Driesen


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.

like image 25
Latin Warrior Avatar answered Oct 30 '22 01:10

Latin Warrior