Monitoring Changes in an Array of Objects with Angular's $watch Feature

Imagine having an array of animal objects linked to the scope. Each object contains a 'name' field and a 'sound' field.

After that, I set up a $watch on the array with the objectEquality flag set to true (the third argument).

Then, in the view, I generate a button for each animal using an ng-repeat over the animals array. When clicked, the corresponding animal object is passed to the handling function.

If I were to update the name of one of the animals in the click handler, the change would be detected by the $watch, allowing me to manage it in the listener function.

However, the problem arises when I replace one of the animal objects with a new object instead of simply changing its properties. In this scenario, the $watch fails to recognize the change despite the clear modification in the array of objects. The listener does not get triggered.

You can see an example of this outlined situation in the following plunkr:

http://plnkr.co/edit/PHXq32?p=preview

Answer №1

AngularJS has no connection to this topic Remember, JavaScript operates on pass by value What does it really mean? Let's discuss how it works with primitives, arrays, and objects

  1. Primitives - When you pass a primitive to a function, you are simply passing the value itself. Any changes made to the value within the function will not affect the original value outside of it.

    function testPrimitive(prm){
      prm = prm+1;
    }

    var prm = 1;
      testPrimitive(prm);
      console.log(prm) //prm remains as 
    still 1

  2. Objects and Arrays - When passing objects or arrays, you are actually passing a reference to the object. This means that modifying a property of the object in a function will reflect those changes outside of it. However, creating a new object inside the function will not affect the original object. Let's see an example.

    var foo = {id:1, name:'iamfoo'}, bar = {id:2, name:'iambar'};
    //two objects are created with references ref1 and ref2 assigned to foo and bar respectively

    function updateObj(o1, o2){
      o1.name='changed'; 
      //o1 is still referencing the same object and updates its property.
      o2 = {id:3, name:'iamnew'}; 
      //A new object is created at ref3 and assigned to o2. Note that ref2 remains unchanged.
    }

    updateObj(foo, bar); //ref1 and ref2 values passed here

    console.log(foo);//outputs {id:1, name:'changed'}
     console.log(bar);
     //bar remains {id:2, name:'iambar'} as it still points to ref2

In your scenario, you're creating a new object inside an array which loses its reference once outside the loop. Use

animal.name ='Billy'; animal.sound='baaaa';
instead within the function

A helpful article on this topic:

Although these concepts may seem basic, many people are unaware or confused about them.

Answer №2

Consider passing $index as an argument to your function and then implement the following:

$scope.animals[index] = {name:'Billy', sound:'baaaa'};

This should resolve the issue.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Angular JS form cloning feature

I'm facing a challenge in creating a dynamic form with multiple sections. At the end of the form, I want to include a "Add New Form" button which will duplicate the existing form below it, each with its own save button. What's the most effective ...

Executing asynchronous JavaScript calls within a loop

I've encountered an issue with asynchronous calls in JavaScript where the function is receiving unexpected values. Take a look at the following pseudo code: i=0; while(i<10){ var obj= {something, i}; getcontent(obj); / ...

Controlling the angular bootstrap modal form with ease

I am having trouble accessing the form in the modal controller (Plunkr). The variable myForm doesn't seem to be accessible. How can I make the alert call work correctly: angular.module('plunker', ['ui.bootstrap']); var ModalDemoCt ...

Tips for ensuring that a nested object in an array contains only a single object

My array is structured like this: [ { object1:{ childObj1:[grandChild1,grandChild2], childObj1, childObj1} }, { object2:{ childObj1:[grandChild1,grandChild2], childObj1, childObj1} }, { object3:{ childObj1:[grandChild1,grandChild2 ...

Improving the efficiency of my conditions in a function with Vue JS

Does anyone have any suggestions on how to optimize this function? I feel like it could be shortened to improve its efficiency. Any help or advice would be much appreciated. Function: onStudentActionSelect: function () { if (this.selectedRows.length ...

The D3.js text element is failing to show the output of a function

I'm having an issue with my chart where the function is being displayed instead of the actual value. How can I make sure the return value of the function is displayed instead? The temperature values are showing up correctly. Additionally, the \n ...

Unable to track user (Mineflayer - Node.js)

Trying to track a player using the mineflayer library in Node.js, but encountering an error within the source code of the library itself. Attempted code: const mineflayer = require('mineflayer'); const { pathfinder, Movements, goals } = require( ...

Automatically use JavaScript to send an email to my email address

I have a question I'm trying to solve: Is there a way to send myself an email notification (using a different address) when a specific event occurs in Javascript or Node.js? For example: if (100 > 90) { emailto="xxxxx.gmail.com" subject="It happ ...

Error Encountered: AngularJS Form Email - SyntaxError: An unexpected token '<' was found in the code

My attempt to send an email from my AngularJS website involves the following setup: Contact.index.html: <form name="userForm" class="well form-search"> <input type="text" ng-model="name" class="input-medium search-query" placeholder="Name" ...

What can be done to address the issue of v-model select option onchange displaying the previously selected value or becoming stuck on a static value rather than updating

Whenever I navigate to the message page and select a device, the v-model selected value changes. However, if I go to the device or contact page, the v-model selected value remains unchanged or goes back to the last selected value. Below is the function in ...

Using JavaScript to convert date and time into ISO format

Similar Question: How do I output an ISO-8601 formatted string in Javascript? I've been attempting to change a date and time input into an ISO format but keep encountering the error .toISOString is undefined. It seems like I must be overlooking s ...

Display the translated text to the user while storing a different value in the database using AngularJS and Angular-Translate

Currently utilizing AngularJS and attempting to utilize $translate for translations. I am facing an issue with a dropdown list where I display translated options for the user. For instance, in English = "Red" and in French = "Rouge", etc. The problem ar ...

Steps to modify the servletRequest's content length within a filter

My main objective is to secure the POST body requests sent from my web application to my service by encrypting them. This encryption process takes place within a filter in my system. However, I've encountered an issue related to content length. When ...

What is the best way to convert $('input[type=text]') into vanilla JavaScript?

How can I change this to plain JavaScript? I've been struggling to find a solution, any pointers? ...

How can you ensure that a function is only executed in AngularJS when the element is visible?

I want to execute a function only when an element is visible. I am utilizing Bootstrap to manage the element's visibility. <td class="hidden-xs col-sm-4 col-md-4 col-lg-4" ng-if="dataObject.property==false" ng-class="{'custom_class& ...

Creating a Vue Directive in the form of an ES6 class: A step-by-step

Is it possible to make a Vue directive as an ES6 Class? I have been attempting to do so, but it doesn't seem to be working correctly. Here is my code snippet: import { DirectiveOptions } from 'vue'; interface WfmCarriageDirectiveModel { ...

What is the best way to style the current element being targeted in React?

In my React application, I am trying to dynamically adjust the height of a textarea element based on its content. I want to achieve this by utilizing an 'onchange' listener to trigger a resize function. While I have successfully implemented the ...

Tips for implementing a JavaScript Material Design framework in ReScript code?

I am attempting to integrate the material-ui library into a Rescript/React application. The code snippet below demonstrates how to display a button: @module("@material-ui/core/Button") external button: string = "default" @react.compone ...

Iterate through the xml.documentElement in a loop

I want to show 8 men and 2 women in SVG format. However, my current function only displays one man and woman. How can I add a loop to make this work for all individuals? for (i = 0; i < Serie[n].Number; i++) { return xml.documentElement } The data arr ...

Angular ngClick on a rectangle within an SVG element

Need to trigger angular click functions on rects in an svg. <rect data-ng-click="scrollToAnchor('siteHeader')" fill="#010101" width="501" height="81"></rect> Here's the function: $scope.scrollToAnchor = function(anchor) { $a ...