Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to trace source of $watch model updates in AngularJS?

In my multi-user AngularJS app, I have a model object on my scope. This model can be manipulated by both user input and server updates.

I have a $watch observer to track the model and update the UI. Is it possible to determine the source/reason of my model update from within my $watch function? Without that check, I have problems with feedback loops (e.g. UI→Server→UI).

UPDATE: some code

Controller:

$scope.elementProperties = { left: 0 };

$scope.$watch('elementProperties.left', function(newVal, oldVal) { changeSelectedElementProperty('left', newVal, oldVal); } );

Directive:

angular.module('myapp.ui-editor').directive('myappPropertiesPanel', function () {
    return {
        templateUrl: 'views/ui-editor/myappPropertiesPanel.html',
        restrict: 'A',
        scope: { elementProperties: '=' },

        link: function postLink (scope, element, attrs) {
            scope.$watch('elementProperties.left', function(newVal, oldVal) { console.log('PropertiesPanel change left', newVal, oldVal); } );
        }
    };
});
like image 746
Tom Söderlund Avatar asked Dec 28 '13 00:12

Tom Söderlund


People also ask

How does $Watch work in AngularJS?

What is the angular JS watch function? The angular JS $watch function is used to watch the scope object. The $watch keep an eye on the variable and as the value of the variable changes the angular JS $what runs a function. This function takes two arguments one is the new value and another parameter is the old value.

What is ngRepeat?

AngularJS ng-repeat Directive The ng-repeat directive repeats a set of HTML, a given number of times. The set of HTML will be repeated once per item in a collection. The collection must be an array or an object. Note: Each instance of the repetition is given its own scope, which consist of the current item.

How to change URL path in AngularJS?

To change path URL with AngularJS, $location. path() is passed the new URL as a parameter, and the page is automatically reloaded. This means that if you ever make a change to the URL in an Angular application, then the partial and controller will be reloaded automatically.


1 Answers

One way of achieving this is by using events instead of $watch

See working plunker here

In my plunker, I've put in a $interval that will simulate a web service call by changing the value every few seconds.

Here is what you can do.

In the then handler of your http call, before you set the new value retrieved from the web service to the model, publish an event with a payload containing the old value and the new value like below:

$http.get('url goes here')
 .then(function (response) {
     scope.$broadcast('UPDATE_FROM_SERVER',
                      {oldValue: scope.elementProperties.left, newValue: response.data.left});
     scope.elementProperties.left = response.data.left;
  };

Then, in your form control, where the user will change the value, attach an ng-click like below:

ng-change="userChangeHandler(elementProperties.left, '{{elementProperties.left}}')

Notice the quotes around '{{elementProperties.left}}'. This will ensure that the change handler function will get the old value of the property.

Now, you can listen to these change events like below:

  $scope.$on('UPDATE_FROM_SERVER', function (event, changes) {
    // This code will be invoked when the data is changed by the server
    $scope.messages.push('Data changed by Server from ' + changes.oldValue + ' to ' + changes.newValue);
  });

  $scope.$on('UPDATE_FROM_USER', function (event, changes) {
    // This code will be invoked when the data is changed by the user
    $scope.messages.push('Data changed by User from ' + changes.oldValue + ' to ' + changes.newValue);
  });
like image 149
CodeWarrior Avatar answered Oct 10 '22 17:10

CodeWarrior