Is there a way to monitor an object for changes in any of its properties, and retrieve the name of the property that changed (excluding newValue
and oldValue
)?
Can this be accomplished?
Is there a way to monitor an object for changes in any of its properties, and retrieve the name of the property that changed (excluding newValue
and oldValue
)?
Can this be accomplished?
Although this question was posted two years ago, I recently encountered the same issue and wanted to share my solution. In previous versions like 1.2, you could access the changed property by referencing this.exp
in the watch function. However, this method was deprecated for performance reasons. The simplest way to retrieve the changed property is by iterating through the new and old objects and comparing their values based on the property name.
$scope.settings = {
'opt1' : 'something',
'opt2' : 'something else',
'opt3' : 'another something',
};
$scope.$watchCollection('settings', function(newObj, oldObj) {
// Iterate through the new object and compare
angular.forEach(newObj, function(val, key) {
if(newObj[key] !== oldObj[key]) {
// settings[key] has been changed
}
});
}, true);
Unfortunately, it is not possible to directly access all the detailed information about changes in a watched object in Angular. The system only provides the new and previous values of the object being observed.
This can be noticed by examining the internal workings of the Angular digest loop:
// This section includes only the essential part of the code
if ((watchers = current.$$watchers)) {
while (/* iterate over watchers */) {
// Comparing the current value with the last known value
if ((value = watch.get(current)) !== (last = watch.last)) {
// The callback function is triggered with the entire values (new and last) as parameters.
watch.fn(value, ((last === initWatchVal) ? value : last), current);
}
}
If you really need a comprehensive comparison of object properties, one approach could be to manually enumerate the properties and compare them individually. Alternatively, you may consider using a third-party library for this purpose. A quick search on NPM led me to this option: deep-diff (which is also available through Bower). If you decide to utilize it, the implementation could resemble the following:
$scope.$watch('watchedObject', function(newValue, oldValue) {
var differences = diff(newValue, oldValue);
// At this point, you can examine the differences array to identify any specific changes
});
Observing an object is a challenging task if you don't have the variable name in your $scope
.
Imagine you have an object that you wish to monitor at $scope.myobject
. The first step is to go through its properties:
var objProperties = []
angular.foreach(myobject, function(value, key) {
objProperties.push("myobject." + key);
});
objExpression = "[" + objProperties.join(",") + "]";
//objExpression will look like "[myobject.a, myobject.b, myobject.c, ...]"
Next, you need to watch over this array:
$scope.$watch(objExpression, function(newValue, oldValue){
//perform iteration here
});
A crucial point to remember is that you have to compare the elements of the newValue
array with the ones in the oldValue
array and reference objProperties
to determine which field has actually changed.
This method may not be the most elegant solution...
Looking to create a directive that can dynamically append HTML content within a div element. Specifically, I need this directive to handle HTML data fetched from the server using an $http post request. <div id="invoice_template_preview" ng-bind-h ...
After organizing the file structure of my web app, utilizing RequireJs and Backbone.Marionette, it now looks like this: |- main.js |- app.js |- /subapp1 |- subapp1.js |- subapp1.router.js |- /subapp2 |- subapp2.js | ...
My goal is to trigger a modal window when a specific div is clicked using bootstrap modal. However, upon clicking the div, the screen darkens but the modal body fails to appear. Code: <html> <head> <title></title> ...
Currently, I am working on implementing a more intricate version of a behavior inspired by Angular Material's tutorials. In my simplified example, an Angular Material table is populated with data from a string array. The first column contains input fi ...
When I make an app.get request in my server.js file, I retrieve a dataset from MongoDB and then render my page while passing the data to it. Here is an example: //page load app.get('/', (req, res) => { //find all data in test table ...
I have a basic form on my website that includes options like: Select 1 and Select 2. I would like to set it up so that if I select value Home in Select 1, the value in Select 2 changes to something like residence. How can I achieve this using a database? ...
UPDATE: Check out this answer. I have a complex query related to jQuery/JavaScript. I came across a post dealing with a similar issue here, but my code structure is different as it does not involve raw HTML or anchor tags. Essentially, I am working on ...
I am having trouble getting my javascript to work properly. My javascript files are located in the public/javascripts directory. app.js app.use(express.static(path.join(__dirname, 'public'))); views/layout.pug doctype html html head ti ...
Issue I have been searching for solutions to my problem with no luck. I have a table containing multiple rows, each row having a checkbox. I am trying to implement a "select all" and "deselect all" functionality for these checkboxes. Below is an example o ...
I have created a new Angular component with the following code: import { Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { HttpClient } from '@angular/common/http'; @Compone ...
I am currently working on a vertical accordion menu that opens on hover, stays open, and closes when other items are hovered. The great assistance I received from @JDandChips has been instrumental in getting this feature up and running. Now, my main focus ...
Dealing with a form that can take a significant amount of time to submit due to posting data to multiple APIs is not uncommon. Normally, I display a message in a bootstrap modal asking the user to wait patiently without clicking the back button. This modal ...
I am having an issue where elements I want to drag on a canvas are not appearing next to each other as expected. Instead, they are overlapping: To make these elements draggable, I am utilizing the dragElement(element) function from https://www.w3schools.c ...
I'm working with angular ui-router and I want to display a different template for a specific state depending on a variable in the main body scope. However, when I include this conditional using $scope.data, nothing happens. The console.log() doesn&apo ...
I am a beginner with canvas and game development. I am currently working on a project where a car moves in a straight line, but I want to add functionality for the car to turn anti-clockwise when the left key is pressed, and clockwise when the right key is ...
Here is a snippet of my PHP file: <?php $myObj = array( "name"=>"John" , "age"=>"30" , "post"=>[ "title"=>"What is WordPress" , "excerpt"=>"WordPress is a popular blogging platform" , ...
While doing some research, I came across an issue. I have a page called specifications.html with three links: details.html?id=1, details.html?id=2, and details.html?id=3. My goal is to display the details of each link when someone clicks on it. For examp ...
I am attempting to create a variable that will set a specific property of an object retrieved through the get method. While using console.log in the subscribe function, I am able to retrieve the entire array value. However, as a beginner, I am struggling ...
FiltersManager.getAllServices({ callback : updateServiceFilter, errorHandler : function(message) { alert(message); } }); Although I throw an exception when an error occurs in th ...
I am facing a challenge in making a div vanish with the class 'backarea' while simultaneously displaying another div with the class 'successLog' on the screen. The catch here is that I want this transition to occur only when specific us ...