suMi suMi - 2 months ago 13
Javascript Question

Angular watch issue

It's the first time I'm using Angular's watch function and apparently I don't get it to work.
I have a service called

apiService
, which has a variable
myFile
. I am injecting the service into my controller and want to watch the
apiService.myFile
value for a change. Unfortunately the watch only gets called on opening the webpage, not when the
apiService.myFile
variable actually changes. Here is the code for the watch:

$scope.$watch(function(){return apiService.myFile}, function (newVal, oldVal, scope) {
console.log("service changed: "+newVal +" : "+oldVal+" : "+ scope);
});


Why isn't it being called when
myFile
changes?

UPDATE 1:
this is how I update the value of
apiService.myFile
inside the service

ApiService.prototype.uploadFile = function(fileContent) {
$.ajax({
url: "/space_uploadFile/",
type: "POST",
dataType: "json",
data: {
fileContent: fileContent
},

contentType: "application/json",
cache: false,
timeout: 5000,
complete: function() {
//called when complete
console.log('process complete');
},
success: function(data) {
this.myFile =data;
console.log("this.myFile: "+this.myFile);
console.log('process success');
},
error: function() {
console.log('process error');
},
});

};

Answer

I added this inside a plunkr (as you didn't) and this works for me:

Sidenote: next time create an example demonstrating your problem (plunkr) so we can eliminate the case of your problem (e.g. typo).

var app = angular.module('app', []);

app.controller('mainController', function($scope, apiService) {

  $scope.changeValue = function() {
    apiService.myFile += "!";
  };

  $scope.$watch(function(){return apiService.myFile}, function (newVal, oldVal, scope) {
    console.log("service changed: "+newVal +" : "+oldVal+" : "+ scope);
    $scope.someValue = newVal;
  });
});

app.service('apiService', function() {
  this.myFile = "Test";
});

And the corresponding HTML:

<body ng-controller="mainController">
  <h1>Hello Plunker!</h1>
  {{someValue}}
  <button ng-click="changeValue()">Click</button>
</body>

https://plnkr.co/edit/DpDCulalK1pZ8J0ykh2Z?p=preview

BTW: The $watch part is a copy from your question and it simply works for me.

Edit: Apparantly the OP was using $.ajax to do ajax calls and the value was updated inside the succeshandler (outside the Angular context). So there was no digest cycle triggered here. To fix this you should use the $http service provided by angular (or work your way around it without).

var self = this;
self.$http.post("/space_uploadFile/",
{ fileContent: fileContent },
{ 
    cache: false,
    timeout: 5000
})
.then(function (data) {
    self.myFile = data;
    console.log("self.myFile: " + self.myFile);
    console.log('process success');
},
function () {
    console.log('process error');
});

Edit2: Apparantly the OP was also using this in the succeshandler to acces variable on the controller. This won't work, so I used the self pattern in the sample above to solve it.