Héctor León Héctor León - 6 months ago 833
AngularJS Question

AngularJS +1.5 How can a Parent controller pass data to a component Controller

I have a component like:

Check Plunkr Example ( Updated and Working with the solution :) Thanks )

my-component.js declaration

(function() {
'use strict';
angular
.module('app')
.component("myComponent", {
bindings: { obj: "=" },
controller: "ComponentController",
controllerAs: "vm",
template:
'<section class="result"><h2>{{vm.title}}</2>' +
'<h3>Using the Parent Controller values</h3>' +
'<ul><li>{{ vm.obj.a }}</li><li>{{vm.obj.b}}</li></ul>' +
'<h3>Using the Children controller values:'+
'<ul class="component-controller"><li>{{ vm.copiedObj.a }}</li><li>{{vm.copiedObj.b}}</li></ul>' +
'</section>'
});

})();


my-component controller

(function() {
'use strict';
angular
.module('app')
.controller('ComponentController', ComponentController);

function ComponentController() {
var vm = this;

vm.title = "I'm the Children controller"

vm.copiedObj = vm.obj; // This should store the myObj variable located in the MainController
}

})();


and a Parent Controller

(function() {
'use strict';
angular
.module('app', []);
})();


// app.controller.js
// ///////////////////
(function() {
'use strict';
angular
.module('app')
.controller('MainController', MainController);

function MainController() {
var vm = this;

vm.title = "I'm the Parent controller";

vm.myObj = {
a: "I'm the first value",
b: "I'm the second value"
};

}
})();


So if i have a template like

<body ng-controller="MainController as vm">

<h2>{{vm.title}}</h2>

<my-component obj="vm.myObj"></my-component>

</body>


The important line is where i have obj="vm.myObj" right ?
I have something wrong because isn't even taking the vm.title :S

I don't want just to print the vm.myObj values into the component,
i want the vm.obj.value from the ParentController to be accessible & stored in the ComponentController.

Answer

The way we do it with components is using the bindings property. It’s simplified version of the directives’s scope and bindToController properties combined.

In a directive, the scope property allows us to define whether we want to inherit or isolate the $scope. That choice has, with time, been deduced to a sensible default to almost always make our directives have isolate scope. And with the addition of the bindToController property, we can define which properties we want to pass down to the isolate scope and bind directly to the controller.

In a component, with the bindings property this repetitive process is removed as the $scope by default is always isolate.

General Example:

// directive
.directive(“myDirective”, function myDirective() {
    return {
        scope: {},              // isolate scope
        bindToController: {
            value: “=”          // two-way binding
        }
    };
});

// component
.component(“myComponent”, {
    bindings: {
        value: “=”              // two-way binding
    }
});

Detailed Example:

angular
    .module(“myApp”)
    .controller(“MyController”, function MyController() {
        var vm = this;

        vm.myObj = {
            a: 1,
            b: 2
        };
    })
    .component(“myComponent”, {
        bindings: { value: “=” },
        controller: “MyComponentController”,
        controllerAs: “vm”,
        template: “<ul><li>vm.value.a</li><li>vm.value.b</li></ul>”
    });

In your template, you can pass down the data like so:

<div ng-controller=“MyController as vm">
    <my-component value=“vm.myObj”></my-component> 
</div>

As explained above, the data is bound to and accessible in the (component's) controller by default.

Note that we’re using two-way binding here. Another addition that is available as of version 1.5 and is specific to components is the < symbol which denotes one-way bindings. Check out the “Component-based application architecture” section in the official documentation for more information.