usersam
usersam

Reputation: 1235

angularjs how to access controller $scope variable in directive isolated scope

In angularjs I have been trying to access main controller $scope variable in my directive isolated scope.

My html code,

  <body ng-controller="MainCtrl">
    <div id="TestContainer" class="TestContainer" ng-init=Intialfunc()>
             <collection collection='testdata'>{{testdata}}</collection>             
        </div>
  </body>

My directive code,

    var app = angular.module('plunker', []);

app.directive('collection', function () {       
    return {
        restrict: "E",
        replace: true,
        scope: {collection: '='},
        //controller: 'TreeController',
        //bindToController: true,       
        template: "<ul><member ng-repeat='member in collection' member='member'></member></ul>"         
    }
})

app.directive('member', function ($compile) {
    var linkerfunc = function(scope, element, attrs) {  
                    var collectionSt = '<collection collection="member.children"></collection>';
                    $compile(collectionSt)(scope, function(cloned, scope)   {                                           
                        element.append(cloned); 
                     });                    
    }
    return {
        restrict: "E",
        replace: true,
        scope: {member: '=', ShowDetailsCtrlFunc : '&'},
        template: "<li><span ng-click=ShowDetailsCtrlFunc()>{{member.NodeName}}</span></li>",       
        controller: 'MainCtrl',
        //controllerAs: 'MainCtrl',
        //bindToController: true,
        link: linkerfunc        
    }
})

My controller code,

app.controller('MainCtrl', function ($scope) {      

    $scope.Intialfunc = function() { 
        $scope.testdata = []
        var myjsondata = JSON.parse('{ "NodeName": "Parent", "children": [ { "NodeName": "mychild", "children": [ { "NodeName": "chld1", "children": [] } ] } ] }');
        $scope.testdata.push(myjsondata);
            console.log($scope.testdata) //This one is showing
        }       

    $scope.ShowDetailsCtrlFunc = function(element,event) {
            console.log("in function ShowDetailsCtrlFunc"); // coming to this fucntion on click.        
            console.log($scope.testdata) // but this one is not showing . shows undefined.
            //event.stopImmediatePropagation();         
      };
});

it is coming to the function but not showing the controller $scope. I have created a plunker ,

plunker

Please help me. I have been struggling for many days.

Upvotes: 1

Views: 3560

Answers (3)

Ayush Agrawal
Ayush Agrawal

Reputation: 379

Lets Begin with the query you have. You want to call a function from link inside the directive even when the scope is isolated. It's simple you want to access parent scope. Here's the code you can use to access parent scope.

    scope.$parent.yourFun();

    //or you can do this by the code give below.
    //Inside Directive Use this.
    scope:{
        fun:"&"
    },

    //now you can call this function inside link
    link:function(scope, element,attr){
        scope.fun();

    }

Upvotes: 0

rmlan
rmlan

Reputation: 4657

You need to add a function expression to both of your directives' isolate scopes in order to properly call a function in your parent scope. Taking your original code, it should look something like this:

var app = angular.module('plunker', []);

app.directive('collection', function () {       
    return {
        restrict: "E",
        //replace: true, <- this is deprecated and should no longer be used
        scope: {
            collection: '=',
            onMemberClick: '&'
        },      
        template: "<ul><member ng-repeat='member in collection' member='member' on-click='onMemberClick()'></member></ul>"         
    }
})

app.directive('member', function ($compile) {
    return {
        restrict: "E",
        //replace: true, <- this is deprecated and should no longer be used
        scope: {
            member: '=', 
            onClick : '&'
        },
        template: "<li><span ng-click='onClick()'>{{member.NodeName}}</span></li>"       
    }
});

And you original html should look something like this:

<body ng-controller="MainCtrl">
  <div id="TestContainer" class="TestContainer" ng-init=Intialfunc()>
    <collection collection='testdata' on-member-click='ShowDetailsCtrlFunc ()'>{{testdata}}</collection>             
  </div>
</body>

Argument binding

If you would like to actually know which member was clicked, you'll need to bind arguments to your function calls.

var app = angular.module('plunker', []);

app.directive('collection', function () {       
    return {
        restrict: "E",
        scope: {
            collection: '=',
            onMemberClick: '&'
        },      
        template: "<ul><member ng-repeat='member in collection' member='member' on-click='onMemberClick({member: member})'></member></ul>"         
    }
})

app.directive('member', function ($compile) {
    return {
        restrict: "E",
        scope: {
            member: '=', 
            onClick : '&'
        },
        template: "<li><span ng-click='onClick({member: member})'>{{member.NodeName}}</span></li>"       
    }
});

Html:

<body ng-controller="MainCtrl">
  <div id="TestContainer" class="TestContainer" ng-init=Intialfunc()>
    <collection collection='testdata' on-member-click='ShowDetailsCtrlFunc (member)'>{{testdata}}</collection>             
  </div>
</body>

MainCtrl:

app.controller('MainCtrl', function ($scope) {      

    $scope.Intialfunc = function() { 
        $scope.testdata = []
        var myjsondata = JSON.parse('{ "NodeName": "Parent", "children": [ { "NodeName": "mychild", "children": [ { "NodeName": "chld1", "children": [] } ] } ] }');
        $scope.testdata.push(myjsondata);
            console.log($scope.testdata) //This one is showing
        }       

    $scope.ShowDetailsCtrlFunc = function(member) {
            console.log("In show details function");
            console.log(member);       
      };
});

plunker

Upvotes: 2

Alexandre Picard
Alexandre Picard

Reputation: 172

In your app.directive, just put scope : false.

Your directive will use the same scope as his parent scope.

Upvotes: -1

Related Questions