Search code examples
javascriptangularjsangularjs-directivedirective2-way-object-databinding

2 way data binding directive angular


im confused about 2 way data binding in angular. Look at the code! the var bah can access parent object $scope.something but when i click the button, the value in controller changed to false but not in directive. whats wrong? is that a bug?

how to solved this? thanks to help me, hope u please write an example to or ref links

HTML

<div ng-controller="myController">
  show me something {{ something }} <br>
  <button ng-click="toggleSomething"><button>

  <!-- this is a canvas -->
  <my-directive></my-directive>
</div>

JS

angular.module('fooBar',[]).controller('myController', ['$scope', function($scope) {
   // this is the something
   $scope.something = true;

   $scope.toggleSomething = function(){
     if($scope.something) { 
       $scope.something = false 
     } else { 
       $scope.something = true 
     }
   }

}]).directive('myDirective', function(){
  return {
    template: '<canvas width="500px" height="500px"></canvas>',
    link: function(scope, el, attr) {
      //how to access that 'something'
      var bah = scope.$parent.something;
    }
  };
});

UPDATE Really thanks to you all. especially to u @immirza

im so sorry i cant reply u one by one. it just add $parent

//how to access that 'something'
var bah = scope.$parent.something

Solution

  • I've put up a plunker with your code and added two-way binding to the directive. you can see it at plnkr

    angular.module('fooBar',[]).controller('myctr', ['$scope', function($scope) {
       // this is the something
       $scope.something = true;
    
       $scope.toggleSomething = function(){
         if($scope.something) { 
           $scope.something = false 
         } else { 
           $scope.something = true 
         }
       }
    
    }]).directive('myDirective', function(){
      return {
        //changed canvas to span so for simplixity.
        template: '<span width="500px" height="500px">{{blah}} --- {{ dsomething }}</span>',
        scope: { dsomething: "=" },
        link: function(scope, el, attr) {
    
          //watching $parent.variable is not recommonded as it makes your
          //directive less reusable and forces who ever wants to use your
          //directive to create the variable.  dsomething will just update
          //nicely w/o any code in this link function. the code below is just to demonstrate
          //how to get it done by using $watch with $parent scope.
    
          //how to access that 'something'
          if(!scope.dsomething){
            scope.dsomething = "something";
          }
    
          //because blah is a local variable and not a two-way binding variable
          //we need to use $watch to update the value.
          //you can use "dsomething" instead of "$parent.something"
          //
          scope.$watch("$parent.something", function(newVal, oldVal){
             scope.blah = newVal;
          })
        }
      };
    });
    

    you can use your directive as:

    <div ng-controller="myctr">
      show me something {{ something }}             <br />
      <button ng-click="toggleSomething()">Update Something</button>
      <button>
        <!-- this is a canvas -->
        <my-directive dsomething="something"></my-directive>
      </button>
    </div>
    

    Pay attention to the ng-click="toggleSomething()". it's a function call not passing a function. ng-click="toggleSomething" won't work.