user3214546
user3214546

Reputation: 6831

How can I have shared scope and pass data in angular directive

In the angular directive I have this

app.directive('myDir', function () {
  return {
    restrict: 'E',
    scope: true,
    template:'<div>{{myindex}}</div>',
    link: function(scope, element, attrs){
      console.log('test', scope.myindex)
    },
   controller: 'myDirController'
  };
})

I use like this

<my-dir> </my-dir>

Now as I want to use it in different templates, I have one function which I want to call like this

// this is inside myDirController        
test: function($scope){
          $scope.myFunction();
        }

Now basically I want to call $scope.myFunction();

This works fine if I have $scope.myFunction(); defined in parent controller.

Buy it's not reusable as in my other controller I want to call $scope.myFunction2();.

So I want something so that I can pass the function name in directive

<my-dir fname="myFunction"> </my-dir>

and that gets called in my directive

The thing is I can't use isolated scope as I need to have access to parent $scope

Upvotes: 2

Views: 589

Answers (2)

7stud
7stud

Reputation: 48659

i want to call $scope.myFunction();

[my directive is] not reusable as in my other controller i want to call $scope.myFunction2();

SO i want something so that i can pass the function name in directive:

<my-dir fname="myFunction"> </my-dir>

1) The attributes in your custom tag are available in the link function, so you can save the value of the fname attribute for future use:

link: function(scope, element, attrs){
  scope.data = {fname: attrs.fname};
},

2) An object's properties can be retrieved using dot notation, e.g. $scope.fname, but the properties can also be retrieved using array notation, e.g. $scope[fname], where fname is a string. And if $scope[fname] is a function, you can execute it by writing $scope[fname]():

app.controller('MyDirCtrl', function($scope) {
  $scope.test = function() {
    var fname = $scope.data.fname;
    $scope[fname]();  //fname property not found in current scope, so parent scope is searched
  };
});

....

<body ng-app="myApp">

  <div ng-controller="Ctrl1">
    <my-dir fname="funcInCtrl1"></my-dir>
  </div>

  <div ng-controller="Ctrl2">
    <my-dir fname="funcInCtrl2"></my-dir>
  </div>

...

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

app.controller('Ctrl1', ['$scope', function($scope) {
  $scope.funcInCtrl1 = function() {
    console.log('funcInCtrl1 called...');
  };
}]);

app.controller('Ctrl2', ['$scope', function($scope) {
  $scope.funcInCtrl2 = function() {
    console.log('funcInCtrl2 called...');
  };
}]);

app.controller('MyDirCtrl', ['$scope', function($scope) {
  $scope.test = function() {
    var fname = $scope.data.fname;
    $scope[fname]();
  };
}]);

app.directive('myDir', function () {
  return {
    restrict: 'E',
    scope: true,
    template:'<div ng-click="test()">click me</div>',

    link: function(scope, element, attrs){
      scope.data = {fname: attrs.fname};
    },

    controller: 'MyDirCtrl', 
  }
})

And, here it is with Controller as syntax:

<body ng-app="myApp">

  <div ng-controller="Ctrl1 as ctrl1">
    <my-dir fname="ctrl1.funcInCtrl1"></my-dir>
  </div>

  <div ng-controller="Ctrl2 as ctrl2">
    <my-dir fname="ctrl2.funcInCtrl2"></my-dir>
  </div>

...

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

app.controller('Ctrl1', function() {
  this.funcInCtrl1 = function() {
    console.log('funcInCtrl1 called...');
  };
});

app.controller('Ctrl2', function() {
  this.funcInCtrl2 = function() {
    console.log('funcInCtrl2 called...');
  };
});

app.controller('MyDirCtrl', ['$scope', function($scope) {
  this.test = function() {
    var fnames = $scope.data.fname.split('.');
    var ctrl_name = fnames[0];
    var func_name = fnames[1];
    $scope[ctrl_name][func_name]();
  };
}]);

app.directive('myDir', function () {
  return {
    restrict: 'E',
    scope: true,
    template:'<div ng-click="mydirCtrl.test()">click me</div>',

    link: function(scope, element, attrs){
      scope.data = {fname: attrs.fname};
    },

    controller: 'MyDirCtrl', 
    controllerAs: 'mydirCtrl'
  }
})

Upvotes: 2

orange
orange

Reputation: 8090

You could use a factory and create different directives with this factory that use your specific function.

module.service('DirectiveFactory', function() {
  this.create = function(fn) {
    return {
      restrict: 'E',
      scope: true,
      template:'<div>{{myindex}}</div>',
      link: function(scope, element, attrs){
        console.log('test', scope.myindex)
      },
     controller: function($scope) {
       // your specific function
       fn();
     }
    };
  };
});

module.directive('my-dir-1', function(DirectiveFactory) {
  function fn1() {
    console.log('my special function call1');
  }
  return DirectiveFactory.create(fn1);
});

module.directive('my-dir-2', function(DirectiveFactory) {
  function fn1() {
    console.log('my special function call2');
  }
  return DirectiveFactory.create(fn2);
});

In your template you'd use:

<my-dir-1></my-dir1>

<my-dir-2></my-dir2>

Upvotes: 0

Related Questions