Using AngularJS's $watchCollection in combination with ng-repeat

Encountering difficulties receiving notifications for changes in a list when utilizing an input field within ng-repeat directly. However, I am able to modify values and receive notifications from $watchCollection.

To illustrate:

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.5/angular.js">
    </script>
</head>
<body>
    <section ng-app="myApp" ng-controller = "TestController">
        <button ng-click = "pushToList()">Add number to list.</button>
        <button ng-click = "changeFirstElement()">Change first element.</button>
        <textarea ng-model = "log"></textarea>
        <ul>
            <li ng-repeat="item in list track by $index">
                <input ng-model="item"> Value: <span ng-bind="item"></span>
            </li>
        </ul>
    </section>
    <script>
        angular.module("myApp", [])
            .controller("TestController", function($scope){
                $scope.log = '';
                $scope.list = $scope.list = [1];

                $scope.pushToList = function() {
                    $scope.list.push(Math.random());
                }

                $scope.changeFirstElement = function() {
                    $scope.list[0] = Math.random();
                }

                $scope.$watchCollection(
                    'list',
                    function(currentValue, oldValue) {
                        $scope.log += [
                            'Current value:',
                            currentValue.toString(),
                            'Old value:',
                            oldValue ? oldValue.toString() : '',
                            '-----',
                            '',
                        ].join('\n')
                    }
                 )
            });
    </script>
</body>
</html>

$watchCollection successfully recognizes changes made through $scope.list[0] = Math.random();. However, modifications via the input fields are overlooked or not detected by $watchCollection. Why is this? Is there an alternative approach?

While I understand that using a deep $watch could be a solution, I am interested in achieving this with $watchCollection for better performance. (Refer to this question for more details).

EDIT:

For a live demonstration, visit the Plunkr page.

Clicking "Add number to list" triggers $watchCollection to detect changes and update the textarea with the current array content. Similarly, changing the first number by clicking "Change first element" prompts $watchCollection to acknowledge the change and update the textarea. However, altering the values using input fields generated by ng-repeat does not produce the expected behavior. It seems that $watchCollection fails to recognize these changes and thus does not update the textarea as anticipated.

Answer №1

The issue lies not with $watchCollection. When using ng-repeat, a new scope is created for each child element. Therefore, if you make changes to an item property while typing in an input field, it only affects the item within that specific ng-repeat child scope since primitive types are being used. In contrast, if you had $scope.list=[{value:1}], you could modify the value in the parent scope and see it reflected in the child scope because list[0] and item reference the same object. However, watchCollection would still not be triggered as it only detects shallow changes.

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

Can one track the moment when a user clicks on an advertisement within a YouTube video?

Can we track when a user clicks on an advertisement within a YouTube video? We have integrated the YouTube API v2 into our website, allowing users to watch videos. The issue is that when a user clicks on an advertisement, the YouTube video pauses automat ...

Activate a Dropdown Menu by Clicking in a React Application

I have a collapsible feature where you can click to expand or collapse a dropdown. Currently, the dropdown can only be clicked on where the radio button is located. I want the entire area to be clickable so that users can choose the dropdown by clicking an ...

Playing embedded YouTube videos automatically in Safari 11 without user interaction

I’m encountering an issue with a simple modal dialog: When a user clicks on a button, the modal overlay appears. An embedded YouTube <iframe> is then added. Everything works smoothly in most browsers, except for Safari 11.1. Safari’s new auto ...

Retrieve a JSON object from a Knockout observable array using the object's ID

I'm struggling to find examples of ko.observablearrays that deal with complex JSON objects instead of simple strings. I have an observable array containing a large JSON object with several properties, and I need to retrieve a specific object based on ...

Include CakePHP named parameters in the URL when selecting from a list

If I have a selection list like the one below: <select name='languages'> <option value='german'>German</option> <option value='english'>English</option> </select> How can I use Jav ...

Maintain user input within the table following a page refresh

I have been working on developing a table that allows users to edit it. I successfully created a script that adds comments to the table, but unfortunately, these comments disappear when the page is refreshed. I understand that I may need some additional to ...

A guide to utilizing asynchandler within a class in Node.js

I'm currently in the process of converting my routers into a class structure, but I'm facing a challenge when trying to wrap the asyncHandler function inside the class. Can anyone provide guidance on how to achieve this? userController.js const ...

Can you explain the concept of a TransientTransactionError within Mongoose (or MongoDB)?

Two important files in my project are server.js and db.js. The db.js file is responsible for interacting with the database using Mongoose, while server.js calls functions from db.js: var mongoose = require('mongoose'); mongoose.connect('&ap ...

The slides in Swiperjs are having trouble moving smoothly

I am experiencing some challenges with swiperjs where the slides are not snapping to the next slide and I am unable to fetch the active index from them. Below is a snippet of my code where I am using typescript, swiperjs version 6.84, and the Ionic frame ...

Tips for parsing data arrays in HTML templates

I have three variables and I created an array where I pushed all these three variables in. In my HTML template, I am using a table. I tried using *ngFor but it is not working, and also attempted string interpolation which also did not work. Currently, I ...

Is AngularJS treating variables as text in their dynamic template directives?

Need help modifying this Angular component: (more details here: https://github.com/khan4019/tree-grid-directive) The issue at hand is simple. The tree-grid component does not allow formatting of specific columns using filters. For example, I want to conv ...

Interactive calendar control for selecting dates in JavaScript

I have implemented two date inputs in my PHP form: Arrival Date Departure Date Currently, when the Date Icon is selected, it displays the CURRENT DATE AND MONTH. What I am looking for is that when the user selects the Arrival Date first and then the De ...

Display all items with pagination in a Material UI Table using React

I have recently implemented pagination in a react data table to handle a large number of entries. I wanted to add an option to display all entries by selecting "all" in the rowsPerPageOptions dropdown menu. Currently, I am able to show the count of all ent ...

In AngularJS, enhance pagination loading by appending a $resource queried array to the end of another

I'm currently working on implementing a loading feature for my Angular application. The goal is to preload page 3 when a user navigates to page 2. Utilizing $resource, I'm querying the Posts resource using Post.query(). By calling Post.query({pa ...

Tips for directing attention to a specific row with an input field in JavaScript

I duplicated a table and added an input field for users to search or focus on a specific row. However, there are two issues: When a user enters a row number, the table displays the wrong row - for example, if the user enters 15, the table shows row number ...

Tips for testing a directive that binds data from a controller

I've created a directive that simply converts the text from the controller to uppercase. For some reason, my unit test code is not working. Any suggestions? Here's the html: <div ng-controller="MainCtrl as main"> <div uppercase&g ...

Utilize Mongoose's post method to generate a fresh collection without any data

Libraries in use: Express, Mongoose, Express-Restify-Mongoose Challenge: I am currently exploring the process of creating a POST request that involves providing the schema within the req.body. My goal is to seamlessly generate a new collection if it doesn ...

Having difficulty naming the request while using ajax to send data to a local server

I have set up an AJAX request to be sent to my PHP server: var xml = new XMLHttpRequest(); xml.open("POST", "request.php", true); xml.setRequestHeader('query','test'); xml.send(); Upon receiving the AJAX data in PHP, I am facing some ...

Can you explain the distinction between key and id in a React component?

I have included this code snippet in the parent component. <RefreshSelect isMulti cacheOptions id='a' key = 'a' components={makeAnimated()} options={th ...

Storing values globally in NodeJS from request headers

What is the most effective way to store and access the value from a request header in multiple parts of my application? One approach could be as shown in the following example from app.js: app.get('*', (req, res) => { global.exampleHeader ...