Is there a way in Angular to respond to model changes without using $ watch?

I use a simple spinner control in AngularJS, and I want to respond to both user input and changes from the +/- buttons. Here is my HTML :

<input type='button' ng-click="MyProperty = MyProperty - 1" value="-"> <input type='text' ng-model="MyProperty" ng-change="log('changed from ngChange')"> <input type='button' ng-click="MyProperty = MyProperty + 1" value="+"> 

But this will only track "user changes", since ngChange only supports user interaction updates by documentaiton

So now I am looking at $scope.$watch as Frederik recommends :

 $scope.$watch('MyProperty', function() { $scope.log('changed from $watch'); }); 

Watch the plunker demo

But that does not seem right.

  • This is not declarative at first, and you need to find the code for MyTestProperty to find this binding.
  • If you want to place $scope.log in a separate model, you need to either enter $scope or bind in the controller. And as I understand it, both paths are not considered best practices.

Some people believe that $watch is bad overall for a number of other reasons. But the solution offered there (which would call log in ngClick directly) doesn't change me too much. Basically, you have to manually track all the changes, and if a new actor appears, you need to copy your logic there.

So the questions will be : is there a way to automatically track model updates without $ watch? And how bad is the idea to implement your own tool for this, if now there is such a way?

+5
source share
3 answers

There are several ways to do this, but the most elegant way requires ngModel input, and then use it to view / control the value.

Below is your Plunker .

 .directive('outputIt', function() { return { restrict: 'A', scope: { outputIt: '&' }, require: '?ngModel', link: function(scope, element, attrs, ngModelCtrl) { ngModelCtrl.$parsers.push(function(val) { //console.log("the model was changed by input") scope.outputIt()(val); }); ngModelCtrl.$formatters.push(function(viewValue) { //console.log("the model was changed from outside."); scope.outputIt()(viewValue); return viewValue; }); } } }) 


To learn more about this, here is a very good article: Atricle

Good luck

+4
source

Have you looked at the ES5 path ? This is essentially a functional function of javascript watch functions. The difference is that you keep the set / get functions encapsulated using the property, while $ watch can be applied externally anywhere.

 var MyCtrl = function(){ this._selectedItem = null; }; Object.defineProperty(MyCtrl.prototype, "selectedItem", { get: function () { return this._selectedItem; }, set: function (newValue) { this._selectedItem = newValue; //Call method on update this.onSelectedItemChange(this._selectedItem); }, enumerable: true, configurable: true }); 
+3
source

Of course use:

 <input type="number" /> 

This will create you spinner =)

-1
source

Source: https://habr.com/ru/post/1200586/


All Articles