Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Watch controller model value from inside directive

Tags:

I am trying to have angular watch the $viewValue of a controller from inside a directive.

fiddle: http://jsfiddle.net/dkrotts/TfTr5/5/

function foo($scope, $timeout) {     $scope.bar = "Lorem ipsum";      $timeout(function() {         $scope.bar = "Dolor sit amet";     }, 2000); }  myApp.directive('myDirective', function() {     return {         restrict: 'A',         require: '?ngModel',         link: function (scope, element, attrs, controller) {             scope.$watch(controller.$viewValue, function() {                 console.log("Changed to " + controller.$viewValue);             });         }     }  }); 

As is, the $watch function is not catching the model change done after 2 seconds from inside the controller. What am I missing?

like image 966
Dustin Avatar asked Jan 28 '13 17:01

Dustin


People also ask

How do you access the directive variable in a controller?

You just create a myVar variable in your controller and pass it to the directive using my-var attribute. Since you are using two way binding, any changes made to myVar by the directive are available in your controller.

What is attrs in AngularJS?

Using attrs you are able to access the attributes defined in your html tag like <fm-rating ng-model="$parent.restaurant.price" symbol="$" readonly="true"> So in this case you will have access to the symbol and readonly attributes.

What is restrict option in directive?

Note: When you create a directive, it is restricted to attribute and elements only by default. In order to create directives that are triggered by class name, you need to use the restrict option. The restrict option is typically set to: 'A' - only matches attribute name. 'E' - only matches element name.


2 Answers

$watch accepts the "name" of the property to watch in the scope, you're asking it to watch the value. Change it to watch attrs.ngModel which returns "bar", now you're watching scope.bar. You can get the value the same way you were or use scope[attrs.ngModel] which is like saying scope["bar"] which again, is the same as scope.bar.

scope.$watch(attrs.ngModel, function(newValue) {     console.log("Changed to " + newValue); }); 

To clarify user271996's comment: scope.$eval is used because you may pass object notation into the ng-model attribute. i.e. ng-model="someObj.someProperty" which won't work because scope["someObj.someProperty"] is not valid. scope.$eval is used to evaluate that string into an actual object so that scope["someObj.someProperty"] becomes scope.someObj.someProperty.

like image 147
Jonathan Rowny Avatar answered Oct 12 '22 05:10

Jonathan Rowny


Wanted to add: in 1.2.x, with isolated scope, the above wont work. http://jsfiddle.net/TfTr5/23/

A workaround I came up with was using the fact that $watch also accepts a function, so you can access your controller using that.

scope.$watch(     function(){return controller.$viewValue},     function(newVal, oldVal){         //code     } ) 

Working fiddle: http://jsfiddle.net/TfTr5/24/

If anyone has an alternative, I would gladly welcome it!

like image 37
wlingke Avatar answered Oct 12 '22 06:10

wlingke