Search code examples
angularjsangularjs-scopeangular-directive

How to change all directive scope value from any one of directive?


I have a directive which was repeatedly n times. I have click event action in every directive. Whenever I click, on click function, It change some scope variable names which defined in directive. But It wont change on all other directives? How to achieve this? I have my plunker here.example

html:

  <!doctype html>
<html ng-app="myApp" >
<head>
  <meta charset="utf-8">
  <title>AngularJS Plunker</title>
  <script>document.write('<base href="' + document.location + '" />');</script>
  <link rel="stylesheet" href="style.css">
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.js"></script>
  <script src="script.js"></script>
</head>
<body ng-controller="MainCtrl">
  this is 1st time: <div sampledirective></div>
  <br />
  this is 2nd time: <div sampledirective></div>
  <br />
  this is 3th time: <div sampledirective></div>
  <br />
  this is 4th time: <div sampledirective></div>
  <br />
  this is 5th time: <div sampledirective></div>
</body>
</html>

I have rendered 'sampledirective' as 5 times in my view.

controller:

  app.controller('MainCtrl', function($scope) {
  $scope.name = 'World';
  $scope.bar ="original bar";
  $scope.term = "original term"
  $scope.temp={};
  $scope.callMethod = function (){
    $scope.term = "Changed term"
    $scope.bar = "Changed bar";
    $scope.temp.callMethod();
  }

});

I have created one object 'temp' in my controller.

directive:

app.directive('sampledirective', function($http) {
  return {
      restrict: 'A',
      scope:true,
       replace: true,
       link:function(s,e,a){
         s.directive_scope="original directive_scope value";
         s.temp.callMethod = function(){

            s.directive_scope="Changed directive_scope value";
         }

       },
       template: '<div ><a ng-click="callMethod()">click_here</a> <span> <b>{{bar}}</b></span>   <span> <b>{{term}}</b></span>  <span> <b>{{directive_scope}}</b></span></div>'
  }

});

In my directive template I have 'temp.callMethod()' which is changed the scope variable value 'directive_scope= Changed directive_scope value'. But It was not reflected in other directives. How to achieve this?


Solution

  • Problem

    Take a closer look at your directive definition, notice you put scope:true in there.

    What it does is it tells Angular to create a new isolated scope for this particular instance of the directive inheriting it from the parent one.

    So you are stuck with 5 directive instances all with their own scopes and when you assign directive_scope in one of them it will in no way reflect in the others. You can read more about directives and their scopes here

    Solution 1

    You should define property in the parent scope and then pass it to the directive using two-way binding

    Controller definition

    app.controller('MainCtrl', ['$scope', function ($scope) {
        $scope.directiveScope = null;
        $scope.temp = {};
        $scope.callMethod = function () {
            $scope.term = "Changed term"
            $scope.bar = "Changed bar";
            $scope.temp.callMethod();
        };
    }]);
    

    Directive definition

    app.directive('sampleDirective', function () {
        return {
            ...
            scope: {
                temp: '=',
                callMethod: '&',
                directiveScope: '=' 
            },
            ...
        };
    });
    

    HTML

    <div sample-directive temp="temp" call-method="callMethod()" directive-scope="directiveScope"></div>
    

    Be aware that each directive instance will write it's own temp.callMethod function to the parent scope's temp property.

    Solution 2

    You should define a service that will store the shared values and inject it in the controller and the directive

    Service definition

    app.factory('sharedData', function () {
        return {
            directiveScope: null
        };
    });
    

    Controller definition

    app.controller('MainCtrl', ['$scope', 'sharedData', function ($scope, sharedData) {
        ...
        $scope.callMethod = function () {
            $scope.term = "Changed term"
            $scope.bar = "Changed bar";
            sharedData.directiveScope = "Changed directive_scope value";
        }
    }]);
    

    Directive definition

    app.directive('sampleDirective', ['sharedData', function (sharedData) {
        return {
            scope: {
                callMethod: '='
            },
            link: function ($scope, $element) {
                $scope.sharedData = sharedData;
            },
            template: '<div><a ng-click="callMethod()">click_here</a> <span> <b>{{bar}}</b></span>   <span> <b>{{term}}</b></span>  <span> <b>{{sharedData.directiveScope}}</b></span></div>'
        };
    }]);
    

    Notice that I changed the output in the template to {{sharedData.directiveScope}}