Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass an object from a nested directive with isolated scope to parent controller scope in angular

I have a directive treeview which contains a nested directive (being the branches) of each item rendered.

In the scope of both directives I have declared two parameters that should be talking to the parent controller.

filter: '&' //binds the method filter within the nested directive (branch) to the method doSomething() in the tree directive attribute which is bound to the html directive that binds to the controller.

iobj: '=' is the two way binding paramter that should be passing the scoped object to the controller. (but currently isn't)

Directive:

app.directive('tree', function () {
    return {
        restrict: 'E', 
        replace: true,
        scope: {
            t: '=src',
            filter: '&',
            iobj: '='
        },
        controller: 'treeController',
        template: '<ul><branch ng-repeat="c in t.children" iobj="object" src="c" filter="doSomething()"></branch></ul>'
    };
});

app.directive('branch', function($compile) {

    return {
        restrict: 'E', 
        replace: true, 
        scope: {
            b: '=src',
            filter: '&',
            iobj: '='
        },

        template: '<li><input type="checkbox" ng-click="innerCall()"  ng-hide="visible" /><a>{{ b.name }}</a></li>',
        link: function (scope, element, attrs) {
           var has_children = angular.isArray(scope.b.children);
            scope.visible = has_children;
            if (has_children) {
                element.append('<tree src="b"></tree>');
                $compile(element.contents())(scope);
            }
            element.on('click', function(event) {
                event.stopPropagation();
                if (has_children) {
                    element.toggleClass('collapsed');
                }
            });
            scope.innerCall = function () {
                scope.iobj = scope.b;

                console.log(scope.iobj);
                scope.filter();
            }
        }
    };
});

HTML:

<div ng-controller="treeController">
    <tree src="myList" iobj="object" filter="doSomething()"></tree>

    <a ng-click="clicked()"> link</a>
</div>

Controller:

app.controller("treeController", ['$scope', function($scope) {
    var vm = this;

    $scope.object = {};
    $scope.doSomething = function () {
        var item = $scope.object;
        //alert('call from directive');
        console.log(item);
   }

   $scope.clicked = function () {
       alert('clicked');
   }
...

Currently I can invoke the function $scope.doSomething from the directive to the controller. So I know that I have access to the controllers scope from the directive. What I cannot figure out is how to pass an object as a parameter from the directive back to the controller. When I run this code, $scope.object is always an empty object.

I'd appreciate any help or suggestions on how to go about this.

like image 718
rlcrews Avatar asked Oct 30 '22 11:10

rlcrews


1 Answers

The & directive binding supports parameter passing. Given your example

scope.filter({message: 'Hello', anotherMessage: 'Good'})

The message and anotherMessage become local variables in the expression bound to directive:

<tree src="myList" iobj="object" filter="doSomething(anotherMessage, message)"></tree>

Here's a sample plunker where the callback parameters are set inside a template.

The documentation clearly states that:

Often it's desirable to pass data from the isolated scope via an expression to the parent scope, this can be done by passing a map of local variable names and values into the expression wrapper fn. For example, if the expression is increment(amount) then we can specify the amount value by calling the localFn as localFn({amount: 22}).

like image 68
miensol Avatar answered Nov 12 '22 15:11

miensol