Reputation: 18801
LIVE CODE: Here
I have injected a service called FileTraversal
added to a module divkick.services
. I Also have a module divkick.container
with a controller named ContainerCtrl
.
I've added a watcher function in ContainerCtrl
and was hopeful it could watch FileTraversal.stuff
array.
Question: I feel this is dumb syntax problem, How do I watch FileTraversal.stuff from ContrainerCtrl
Main App:
(function () {
"use strict";
angular.module('divkick', [
'divkick.services',
'divkick.components',
'divkick.container'
]);
})();
Controller:
(function () {
angular
.module('divkick.container', [])
.controller('ContainerCtrl', ContainerCtrl)
ContainerCtrl.$inject = ['FileTraversal', '$scope', '$timeout'];
/* @ngInject */
function ContainerCtrl(FileTraversal, $scope, $timeout) {
/* jshint validthis: true */
var main = this;
activate();
////////////////
function activate() {
$scope.$watch(
// This function returns the value being watched. It is called for each turn of the $digest loop
function() { return FileTraversal.stuff; },
// This is the change listener, called when the value returned from the above function changes (but not working) :(
function(newValue, oldValue) {
if ( newValue !== oldValue ) {
console.log(newValue);
} else {
console.log('nope');
}
}
);
}
}
})();
Service:
(function () {
"use strict";
var fs = require('fs');
var glob = require("glob");
angular
.module('divkick.services', [])
.factory('FileTraversal', FileTraversal);
/* @ngInject */
function FileTraversal() {
var service = {
stuff: [],
check: check
};
return service;
////////////////
function check(filePath) {
glob(filePath + '/**/*{.png,.jpg,.gif}', function (er, files) {
if(er) return er;
service.stuff = files;
});
}
}
})();
I tried watchcollection like this:
$scope.$watchCollection(
function() { return FileTraversal.stuff; },
function(newValue, oldValue) {
if ( newValue !== oldValue ) {
// Only increment the counter if the value changed
console.log(newValue);
} else {
console.log('nope');
}
}
);
Upvotes: 0
Views: 69
Reputation: 25352
Try watch collection instead of watch
$scope.$watchCollection(function () {
return FileTraversal.stuff;
}, function (newValue, oldValue) {
console.log("check")
if (newValue !== oldValue) {
console.log(newValue);
} else {
console.log('nope');
}
});
N:B:
you didn't add ng-controller in view in your fiddle . may be that's a typo
Upvotes: 1
Reputation: 19238
The problem is that you're using $watch
instead of $watchCollection
.
$watch
is currently looking at a property that points to an array. Even if the array changes, the property that points to the array doesn't change - the pointer is the same. So $watch
doesn't detect this.
If you use $watchCollection
, angular will know to examine the collection to see if any of the elements in the collection have changed.
See The Three Watch Depths of AngularJS for more info.
angular
.module('app', [])
.controller('MainController', MainController)
.factory('Factory', Factory)
;
function MainController(Factory, $scope) {
var main = this;
main.factory = Factory;
main.addToArray = function() {
main.factory.array.push('added');
};
// watching primitive
$scope.$watch(function() {
return Factory.primitive;
}, function(newVal, oldVal) {
if (newVal === oldVal) {
console.log('primitive unchanged');
}
else {
console.log('primitive changed');
}
});
// watching array
$scope.$watchCollection(function() {
return Factory.array;
}, function(newVal, oldVal) {
if (newVal === oldVal) {
console.log('array unchanged');
}
else {
console.log('array changed');
}
});
}
function Factory() {
return {
primitive: 'foo',
array: []
};
}
<!DOCTYPE html>
<html ng-app="app">
<head>
<script data-require="[email protected]" data-semver="1.4.6" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<div ng-controller="MainController as main">
<input ng-model="main.factory.primitive" />
<button ng-click='main.addToArray()'>Add to array</button>
</div>
</body>
</html>
Upvotes: 0