One method of dirty checking using a shared service among controllers is effective, while the other method is not successful

As I was trying to solve the problem of sharing data between two separate controllers, I encountered a curious issue.

Usually, I rely on services for this task and started creating a jsfiddle example, but unfortunately, I couldn't get it to function properly.

After some debugging, I noticed that if I dynamically created the properties in setActivePersonWorks(person), the dirty checking worked and the second controller displayed the correct value.

However, assigning the value in setActivePersonDoesNotWork() did not yield the same result.

By using $timeout(), I could confirm that DataService.badPerson actually contained the correct data.

I'm puzzled by this behavior. It seems that using $apply() would fix the issue, but why does creating values dynamically make things work smoothly?

Here is an example:

var myTest = angular.module("MyTest", []);
myTest.factory("DataService", function () {
    var People = {
        goodPerson: {},
        badPerson: {},
        setActivePersonWorks: function (person) {
            People.goodPerson.name = person.name;
            People.goodPerson.id = person.id;
        },
        setActivePersonDoesNotWork: function (person) {
            People.badPerson = person;
        }
    };
    return People;
});

function ViewController($scope, DataService, $timeout) {
    $timeout(function () {
        DataService.setActivePersonWorks({
            id: 1,
            name: "Good Mark"
        });
        DataService.setActivePersonDoesNotWork({
            id: 2,
            name: "Bad Mark"
        });
    }, 1000);
}

function DetailController($scope, DataService, $timeout) {
    $scope.goodPerson = DataService.goodPerson;
    $scope.badPerson = DataService.badPerson;

    $timeout(function(){
        $scope.message = "DataService has the value: " + DataService.badPerson.name + " but $scope.badPerson is " + $scope.badPerson.name;
    }, 2000);
}

The <html/>

<div ng-app="MyTest">
    <div ng-controller="ViewController"></div>
    <div ng-controller="DetailController">
         <h1>Works: {{goodPerson.name}}</h1>

         <h1>Does Not Work: {{badPerson.name}}</h1>
        {{message}}
    </div>
</div>

Check out the code on jsfiddle

Answer №1

Upon encountering the HTML code:

<h1>Does Not Work: {{badPerson.name}}</h1>

Angular initiates a $watch on the object badPerson. Analyzing your controller, we see that $scope.badPerson is linked to the object DataService.badPerson. Everything seems in order at this point, but here lies the issue:

setActivePersonDoesNotWork: function (person) {
    People.badPerson = person;
}

When this function is called, badPerson is given a new object reference, while the controller still monitors the original reference.

The solution is to use angular.copy() to update the existing badPerson object instead of assigning a fresh reference:

setActivePersonDoesNotWork: function (person) {
    angular.copy(person, People.badPerson);
}

This clarifies why setActivePersonWorks() functions properly - it does not introduce a new object reference.

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

The browser fails to display the canvas when using the fillRect function

As a novice in Canvas, I've been experimenting with some code, but unfortunately, it's not working for me. Here's the code I used. Can someone help me identify the issue? <!DOCTYPE html> <html> <head> <title> 28 ...

Unlocking the request object within a GraphQL resolver with Apollo-Server-Express

My express server is standard and I'm using GraphQL with it const server = express(); server.use('/graphql', bodyParser.json(), graphqlExpress({ schema })); I am wondering how to access the request object within a resolver. Specifically, ...

Guide to setting up npm openlpr in a Node.js environment

After attempting to install the npm node-openalpr package, I encountered an error. What steps can I take to resolve this issue? > <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="cba5a4afaee6a4bbaea5aaa7bbb98bfae5fae5fa">[e ...

Deactivate any days occurring prior to or following the specified dates

I need assistance restricting the user to choose dates within a specific range using react day picker. Dates outside this range should be disabled to prevent selection. Below is my DateRange component that receives date values as strings like 2022-07-15 th ...

Contrasting the use of creating a new Promise and using Promise.resolve

Looking to gain insight into how the NodeJS runtime manages things in the code snippet below: const billion = 1000000000; function longRunningTask(){ let i = 0; while (i <= billion) i++; console.log(`Billion loops done.`); } function lon ...

axios encountered a JSON parsing issue due to an unexpected character in the server's response

I'm encountering an issue with JSON parsing as I attempt to retrieve data from a server endpoint. This is the first instance where Axios is unable to automatically decode the JSON response. Upon inspecting my code, I noticed that Axios is detecting ...

Passing a value to a component to delete a table row in ReactJS using Material UI

My task is to delete a specific table row after clicking. I have two components and have already written a function, handleDelete(), to remove a row from the table. The issue is that whenever I click, it always deletes the last row instead of the one I cli ...

Tips for effortlessly enlarging an element

When you click on "#sidebarnav>li", the following happens: 1) The second child of it - <ul> element will expand and its class toggles between "collapse" and "collapse in". 2) "#sidebarnav>li" will receive the "active" class. 3) The "aria-ex ...

Is there a way for me to determine the dimensions of the webcam display?

How do I determine the width and height of the camera in order to utilize it on a canvas while preserving proportions? I am attempting to ascertain the dimensions of the camera so that I can use them on a canvas. On this canvas, I plan to display live vid ...

What are the steps to create parallel curves in three.js for road markings?

My goal is to create parallel curved lines that run alongside each other. However, when I try to adjust their positions in one axis, the outcome is not what I expected. The code I am using is fairly simple - it involves a bezier curve as the central path ...

Best practices for managing several models within the Ionic framework using PouchDB?

Hey there! I've been diving into PouchDB lately and have a question about handling multiple models. I've noticed that most examples focus on a single model, like the ones found in this tutorial and various to-do app demos where they use db.allDo ...

Is it possible to generate HTML form fields with fixed positions when using Orbeon forms?

Is there a way in Orbeon forms to position input fields at specific coordinates, relative to a background image? I currently have a paper form that fills an entire page. My goal is to use the scanned image of this form as a background and then overlay inp ...

Leverage the power of React by utilizing SVGR to easily integrate SVG files

Wondering if there's a way to bring in an SVG file from my public folder and use it as a React component like this: import { ReactComponent as MySvg } from '/assets/svg/mysvg.svg'; const MyComponent = () => { return ( <div> ...

Exploring IdentityServer3: A Deep Dive into OAuth Flows and Varied Strategies

After developing a REST Web API application, I want to provide other developers with the capability to access those APIs on behalf of the user. To achieve this, I have implemented OAuth authentication with IdentityServer3. Currently, I have successfully ge ...

The result of Coordinates.speed is consistently null

I'm working on a project that involves changing the speed of background particles based on the user's device speed (like when they are in a car or bus). I thought the Geolocation API would be a perfect fit, specifically the Coordinates.speed prop ...

Is there a way to direct the embedded YouTube video on my HTML website to open in the YouTube application instead?

My website has embedded Youtube videos, but when viewing on a mobile browser they open in the default player. I want them to open in the Youtube application instead, as my videos are 360 degrees and do not work properly in the default browser player. ...

Adjusting the width of the final card in the deck grid

Currently, I am utilizing angular-deckgrid for image display purposes. Within a container, there are two columns in which images are displayed with the column-1-2 class according to the documentation. However, in certain scenarios where only one image is p ...

Enhance the existing User model in loopback by adding additional properties and functionalities

In my loopback app, I am looking to create a model that represents a user profile. However, the default User model provided by loopback only includes the properties: username password realm emailVerified I am wondering what is the most effective approac ...

Using specialized directives to communicate with an Api

I am having trouble accessing more than 10 objects from an API and the custom directive is not working as expected. Can anyone provide some suggestions or help? Below is the code snippet that I'm struggling with: mainView.html <div class="panel ...

"Utilize Ajax to dynamically generate options in a dropdown menu with multiple

I am having trouble populating my multiple dropdown list using AJAX. The dropdown list is dependent on another single selection dropdown list. Here is the HTML code: <div class="form-group"> <label for="InputGender">Select Course</ ...