I have this data
in my controller
$scope.data = {
home: {
baseValue: "1",
name: "home"
},
contact: {
baseValue: "2",
name: "contract"
}
// a lot more options
};
with some html like this:
<section class="content row" ng-repeat="item in data">
{{item.name}}
....
</section>
Now, I want to know when the baseValue
is changed but because of I using a objects inside the data variable I can not watch
the property in a simpler way.
I have tried something like this, but I have to loop all the array
$scope.$watch('data', function (newValue, oldValue, scope) {
// some code to compare the tow arrays, line by line
}, true);
How can I do a simpler $watch
to know only when the baseValue
is changed?
Similar questions:
UPDATE 1
I could add an individual watch for each object to know when the baseValue
is changed, but it won't be nice if I had an n
number of objects, not only a couple of objects like in this example
$scope.$watch('data.home', function (newValue, oldValue, scope) {
// do some stuff with newvalue.baseValue
}, true);
$scope.$watch('data.contact', function (newValue, oldValue, scope) {
// do some stuff with newvalue.baseValue
}, true);
... // Adds more individual `watch`
A JavaScript object has properties associated with it. A property of an object can be explained as a variable that is attached to the object. Object properties are basically the same as ordinary JavaScript variables, except for the attachment to objects.
$watch() function is used to watch the changes of variables in $scope object. Generally the $watch() function will create internally in Angularjs to handle variable changes in application.
Just as object properties can store values of any primitive data type (as well as an array or another object), so too can arrays consist of strings, numbers, booleans, objects, or even other arrays.
Based on your question, you can use ngChange to watch changes of baseValue
and trigger the function.
HTML
<section class="content row" ng-repeat="item in data"> Name: {{item.name}} <br/> BaseValue: <input type="text" ng-model="item.baseValue" ng-change="baseValueChange(item.baseValue)"/> </section>
Controller
$scope.baseValueChange = function(baseValue) { console.log("base value change", baseValue); }
If you a more sophisticated version which can get oldValue and newValue, you can refer to this plunkr - http://plnkr.co/edit/hqWRG13gzT9H5hxmOIkO?p=preview
HTML
<section class="content row" ng-repeat="item in data"> Name: {{item.name}} <br/> BaseValue: <input type="text" ng-init="item.oldBaseValue = item.baseValue" ng-model="item.baseValue" ng-change="baseValueChange(item.oldBaseValue, item.baseValue); item.oldBaseValue = item.baseValue"/> </section>
Controller
$scope.baseValueChange = function(oldVal, newVal) { console.log("base value change", oldVal, newVal); }
You can watch an object attribute.
So you can do something like
for(var key in $scope.data) {
if($scope.data.hasOwnProperty(key)) {
$scope.$watch("data['" + key + "'].baseValue", function(val, oldVal) {
// Do stuff
});
}
}
Not tested, but the idea is simple.
In this kind of scenario there is no way to circumvent utilizing multiple watches, another way to do this is by utilizing $watchCollection
to watch the array of object values, you can get this array using the Object.values
function.
scope.$watchCollection(function() {
return Object.values(obj);
}, function(newValues, oldValues) {
// now you are watching all the values for changes!
// if you want to fire a callback with the object as an argument:
if (angular.isFunction(scope.callback())) {
scope.callback()(obj);
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With