1

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
7
  • 2
    how do you know something is not changing in directive? Commented Dec 3, 2015 at 6:54
  • just write console.log(scope.$parent.something).. haha im really basic in js and angular. XD Commented Dec 3, 2015 at 7:03
  • umm oky the thing is console.log(scope.$parent.something); is prints one time (that should be true) if you put it in directive link function isn't it? so how do you manage to check the value after the click in directive to confirm that value is not changing? Commented Dec 3, 2015 at 7:05
  • I believe that accessing a variable from the parent scope that way is just bad design. You should pass the parent's property in as a two-way binding argument to the directive. that way it makes your directive reusable everywhere else; and its parent scope doesn't to have a property named something like in your example. go to this plunker to see an example of how to do so: plnkr.co/edit/?p=preview Commented Dec 3, 2015 at 7:18
  • @K.Toress yeah ur right it just print one time, i check the value after clicking by just see in '{{ something }}' ~NPToita oke i see ur plunker ..on going. :D it just blank plunker.. Commented Dec 3, 2015 at 7:24

3 Answers 3

2

You can directly access the $scope.something in the myDirective without using the $parent because the directive has shared scope

and for your question if you try to detect the something changes inside the directive you cant just put a console.log($scope.something) and check because its executed only one time and after the click its not going to print again, that doesn't mean something is not change inside the directive.

and also you did a mistake in ng-click like ng-click="toggleSomething" it should be ng-click="toggleSomething()" since your calling a function not just a variable.

here is a DEMO

i have put <h1> ... {{ something }}</h1> inside the directive template to show that the something is working as expected inside the directive also.

go though this excellent directive series

Sign up to request clarification or add additional context in comments.

1 Comment

Yeah @K.Toress it work for u but not me. i try to use '$watch' it work fine but i want to know more about 2 way data binding. for your information.. i use createJs to make a physic collision app in canvas not in '<h1>{{something}}</h1>'. i was tried your plunker method before you write but it doesnt work. :D
1

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.

1 Comment

its working nicely in canvas. with $watch and $parent. thanks.. :D
0

The problem is that you are misunderstanding what two way data binding is, basically any element that is two way bound with a directive can be updated by the controller or the directive and the other would immediately see this change reflected in it.

When you access it using $parent you are forcefully reading the value in your directive, and nothing more, no one tells the directive to reevaluate var bah = scope.$parent.something as the value of scope.something has been updated in the parent controller.

1 Comment

yeah i know, im just basic in 2 way data binding, it really like magic in my think. XD Mmm.. can u write an example code. thanks in advance.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.