Watch for changes in a nested collection in Angular using $scope.$watch

Within my Angular application, there is a checkbox list that is dynamically generated using nested ng-repeat loops. Here is an example of the code:

<div ng-repeat="type in boundaryPartners">
    <div class="row">
        <div class="col-xs-12 highlight top-pad">
            <div ng-repeat="partner in type.partners" class="highlight">
                <label class="checkbox-inline">
                    <input type="checkbox" value="partner"
                    ng-model="ids[$parent.$index][$index]"
                    ng-true-value="{{partner}}"
                    ng-false-value="{{undefined}}">
                    <p><span ></span>{{partner.name}}<p>
                </label>
            </div>
        </div>
    </div>
</div>

In the controller:

$scope.ids = [];

$scope.$watchCollection('ids', function(newVal) {
    for (var i = 0, j = newVal.length; i < j; i++) {

        // Create new participatingPatners tier if it doesn't exist
        if(!$scope.report.participatingPartners[i]) $scope.report.participatingPartners[i] = {};

        // Give it an id
        $scope.report.participatingPartners[i].id = i + 1;

        // Map our values to it
        $scope.report.participatingPartners[i].entities = $.map(newVal[i], function(value, index) {
            return [value];
        });
    }

});

The issue arises with the $scope.$watchCollection function, as it stops monitoring changes once all top-level ids have been added. This means that if I select checkboxes from different nested lists, the

$scope.report.participatingPartners
object does not get updated.

Is there a way to continuously monitor changes within ids[$parent.$index][$index], ensuring that my object reflects any updates made to the checkboxes?

Answer №1

When creating a nested array, consider using $watchCollection to monitor changes in the main array ($scope.ids). This method will only detect modifications when the inner arrays are replaced with different objects or initialized for the first time.

Rather than employing

$scope.$watch("ids", function(){}, true)
for a deep-watch that constantly checks for updates on every digest cycle – regardless of user actions – it is more efficient to utilize ng-change to trigger the desired function:

<input type="checkbox" value="partner"
       ng-model="ids[$parent.$index][$index]"
       ng-change="handleCheckboxChanged()">

Utilize the following code to handle checkbox changes without the overhead of unnecessary checking:

$scope.handleCheckboxChanged = function(){

  // Perform necessary tasks previously handled by $watchCollection
}

Answer №2

$watchCollection is quite similar to $watch as it not only checks the object reference, but also goes one level deeper to perform a reference check on its properties.

In order to achieve deep reference checking, you can utilize $watch with the objectEquality flag set to true. This instructs $watch to delve into the nested properties for comparison. Keep in mind that this may impact performance depending on the complexity of the watched object.

$watch(watchExpression, listener, [objectEquality]);

Answer №3

Are you able to pay attention to object equality :

$watchCollection('ids', function(newVal) {

}, true);

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

Leveraging Gatsbyjs to Integrate GraphQL Data with Material UI Library

Just starting out as a Frontend Developer and currently learning Gatsbyjs along with the Material UI library. I'm working on creating a new page using the Material UI Gatsby Starter code available here. However, I've encountered an issue when tr ...

The HTML and JavaScript implementation of the Game of Life is experiencing technical difficulties

I attempted to create my own version of the Game of Life using HTML canvas and JavaScript. With the aid of various online tutorials, I was able to write a piece of code that I am still confident in. However, upon launching the HTML page in the browser and ...

Is there a way to establish the position of a mesh in three.js before integrating it into the scene?

How can I add a mesh to a specific position in the scene using three.js? I attempted the following code without success: // mesh refers to an instance of THREE.Mesh // scene is an instance of THREE.Scene scene.add(mesh) scene.updateMatrixWorld(true) mesh. ...

Displaying a div upon hovering over another div is resulting in numerous server requests and a flickering effect

I am attempting to create a hover effect where one div floats next to another. The layout of the divs is like a grid, placed side by side. Check out my code on this fiddle. Using plain JavaScript, I want to display a second div (div2) floating next to div ...

Design an interactive quarter-circle using CSS styling

My goal is to create this element using CSS, however, the content inside needs to be dynamic. I initially attempted to use border-radius, but realized it is unable to achieve the desired outcome. If anyone has a solution or can offer assistance, I would g ...

What could be the reason behind the absence of this.props.onLayout in my React Native component?

In my React Native app, I have the below class implemented with Typescript: class Component1 extends React.Component<IntroProps, {}> { constructor(props){ super(props) console.log(props.onLayout) } ... } The documentation for the View ...

React Router integration problem with Semantic UI React

Just diving into ReactJS and encountering a problem with using "Menu.Item" (from Semantic UI React) and React Router. I won't include my imports here, but rest assured they are all set up correctly. The constructor in my "App.jsx" looks like this: ...

Display Image After Uploading with AJAX

After spending nearly 3 hours working on implementing file uploads via AJAX, I have finally managed to get it up and running smoothly. Take a look at the code below: View <div class="form-horizontal"> <div class="form-group"> @Htm ...

Fade out effect in jQuery upon reloading the page

Is there anyone who can assist me with this issue? The following script snippet allows a user to delete records from a table connected to a mySQL database. <script type="text/javascript> $(document).ready(function(){ $('form.delete ...

What are the steps to customizing a package on atmospherejs.com within meteor.js?

When working with atmosphere in meteor.js, installing a package is typically as simple as using a single command. However, if there is a need to make changes to a specific package for customization purposes, the process becomes a bit more complex. For ex ...

What is the purpose of using defer="defer" in JavaScript?

I've been experimenting with Three.js and found that it only functions properly when used like this: <script src="script.js" defer="defer"></script> However, I'm puzzled as to why the defer="defer" attribute is crucial... Can anyon ...

Tips for showing form data upon click without refreshing the webpage

Whenever I input data into the form and click on the calculate button, the result does not appear in the salary slip box at the bottom of the form. However, if I refresh the page and then click on the calculate button, the results are displayed correctly ...

Enclosing values in JavaScript literals

I apologize for the inconvenience. I am unsure why it is not functioning properly. If I input <button type="button" onclick="document.getElementById("demo").innerHTML = Date()">click</button> the above code does not work. However, if I u ...

What is the best way to avoid the pipe symbol in jade formatting?

When working with jade, the pipe symbol (|) is utilized for displaying plain text. But what if you need to actually write it on the page? Is there a way to escape it in Jade? ...

What sets apart importing components in computed from importing components in dynamic import in Vue.js?

Imagine there are 4 components available on a page or within a component, and the user can utilize them based on their selection by toggling between Input, Image, Video, or Vudio components. There are two ways to lazily load these components: 1) <temp ...

To begin, select and upload two files for processing. Once complete, you can download the newly generated

I'm encountering difficulties attempting to upload two files to a php script and have the page download a newly merged file without redirecting to a different page. I do not wish to store any files on the server due to their potential size (2MB) as b ...

Launching npm using the command "npm run protractor" results in console errors being thrown upon completing the test

Recently, we made the decision to streamline the installation process of Protractor on local machines by specifying it in package.json rather than installing it individually with the -g flag. The addition we made looks something like this: "scripts": { ...

Is it possible to receive live updates from a MySQL database on a webpage using node.js and socket.io?

I've been following a tutorial that teaches how to receive real-time updates from a MySQL database using Node.js and Socket.io. Check it out here: Everything seems to work fine on the webpage. I can see updates in real-time when I open the page on tw ...

The error message "trying to access markers property of undefined in the render function" occurred

I encountered this error while running my react-native component and need assistance. An error stating "undefined is not an object (evaluating 'this.state.markers.map')" occurred. This error appears in the following locations: c:\proje ...

Unexpected TypeScript issue: Unable to access the 'flags' property of an undefined entity

Upon creating a new project and running the serve command, I encountered the following error: ERROR in TypeError: Cannot read property 'flags' of undefined Node version: 12.14 NPM version: 6.13 Contents of package.json: { "name": "angular-t ...