Is there a way to update an angular.js service object without using extend or copy?

I am working with 2 services and need to update a variable in the first service from the second service. Within a controller, I am assigning a scope variable to the getter of the first service.

The issue I am facing is that the view connected to the controller does not reflect updates when the service variable changes unless I use angular.extend/copy. It seems like setting selectedBuilding below should work without needing to use extend/copy. Am I missing something here, or is this the correct approach?

controller

app.controller('SelectedBuildingCtrl', function($scope, BuildingsService) {
    $scope.building = BuildingsService.getSelectedBuilding();    
});

service 1

app.factory('BuildingsService', function() {
    var buildingsList = [];
    var selectedBuilding = {};
    // buildingsList populated up here
    ...
    var setSelectedBuilding = function(buildingId) {
        angular.extend(selectedBuilding, _.find(
            buildingsList, {'building_id': buildingId})
        );
    };
    var getSelectedBuilding = function() {
        return selectedBuilding;
    };
    ...
    return {
        setSelectedBuilding: setSelectedBuilding,
        getSelectedBuilding: getSelectedBuilding    
    }
});

service 2

app.factory('AnotherService', function(BuildingsService) {
    ...
    // some action triggers, resulting in a building id
    BuildingsService.setSelectedBuilding(building_id);
    ...
});

Thank you for your assistance!

Answer №1

After executing the code snippet below:

$scope.building = BuildingsService.getSelectedBuilding(); 

The $scope.building variable is just a reference to the same object in memory as the selectedBuilding from your service. If you assign a new object to selectedBuilding, $scope.building will still point to the old object, which causes the view not to update. To solve this issue, you should use angular.copy/extend.

If you need to assign new objects to selectedBuilding, consider implementing the following solution:

app.factory('BuildingsService', function() {
        var buildingsList = [];
        var building = { 
            selectedBuilding : {}
         }
        
        var setSelectedBuilding = function(buildingId) {
            //assign a new object to building.selectedBuilding 
        };
        var getSelectedBuilding = function() {
            return building; 
        };
        
        return {
            setSelectedBuilding: setSelectedBuilding,
            getSelectedBuilding: getSelectedBuilding    
        }
    });

To implement this solution, update your views by replacing $scope.building bindings with $scope.building.selectedBuilding.

In my perspective, using angular.copy/extend is a simpler way to avoid unnecessary complexity.

Answer №2

I think it's important to stay actively engaged with your service rather than relying on extensions. By watching the service directly, you can respond to changes more effectively. Here's an example using AngularJS:

app.controller('SelectedBuildingCtrl', function($scope, BuildingsService) {
  // This first function is evaluated on every $digest cycle
  $scope.$watch(function(scope){
    return BuildingsService.getSelectedBuilding();
  // The second function is a callback that handles changes
  }, function(newVal, oldVal, scope) {
    scope.building = newVal;
  }
});

To learn more about $watch, check out: https://code.angularjs.org/1.2.16/docs/api/ng/type/$rootScope.Scope

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

Sharing a Detailed Mongoose Schema

Hey there! So, I've been working on this Mongoose Schema and there seems to be something off about it. The main area of concern is the "region" part. const mongoose = require('mongoose'); const destination = new mongoose.Schema({ ...

Update a specific element within Angular framework

Just starting out with angular and facing a seemingly simple issue that I can't seem to solve despite trying various solutions found on SO. I have created a login component where upon submission, the user is redirected to their profile page. While I a ...

What is the most effective way to save numerical information to a file?

Imagine a scenario where there is an array filled with one million random numbers: [ 0.17309080497872764, 0.7861753816498267, ...] The task at hand is to store these numbers onto a disk for future retrieval. While storing them in text formats like JSON or ...

Creating a stylish gradient text color with Material-UI's <Typography /> component

Is there a way to apply a gradient font color to a <Typography /> component? I've attempted the following: const CustomColor = withStyles({ root: { fontColor: "-webkit-linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)", }, })(T ...

Exploring characteristics within a Three.Js environment in a React application

I have successfully integrated a ThreeJs Scene into a React component, following the approach outlined here. However, I am facing difficulties updating the Scene based on state changes in its parent component. In my setup, users can configure certain prope ...

Trouble with Rails partial refresh using Ajax feature

On the homepage, I would like to display article information to the user. When the user clicks on the My Articles link, the relevant information should be shown without refreshing the entire page: Here is the code for the ArticlesController: def index ...

Transform React.js data from MySql into a variable

Hello there! I encountered an issue while working on coding my web app. **I am looking to execute this class only if the "swishes" value retrieved from a table in my MySQL database is greater than 0.** var thepos = 1; export default class W ...

How can I show a legend entry for every column in Amcharts?

Take a look at this code snippet: http://jsfiddle.net/ouLed1fp/ How can I create a legend entry for each column in the chart? Also, is there a way to display the column names next to them, providing a clear legend? <div id="chartdiv" style="width: 10 ...

Include a for loop in the line graph on Google Charts

I need help figuring out how to use a for loop to iterate over data in order to populate my Google Chart. The code snippet below outlines what I've already tried. var line_div = '2016-08-04,4|2016-08-05,7|2016-08-06,9|2016-08-07,2'; var lin ...

Can you confirm if the user originated from JavaScript when Ajax is sent?

Illustration: Upon using "ajax.send", the file is displayed (for example, "post.php?q=...".) However, by copying the specific "url" and pasting it into the browser with the same parameters, access can also be gained. Hence, is there a way to prevent this ...

Using Javascript, verify if a given URL is legitimate and commences with "http://" or "https://"

I need to validate the authenticity of my URLs, ensuring they begin with either http:// or https://. Here is the regular expression (RegExp) I have been using: private testIfValidURL(str) { const pattern = new RegExp('^(https?:\\/&bsol ...

Implementing file uploads in an Ionic application with a Web API

My dilemma is as follows: I am working with a WEB API where I need to upload images of boards. What do I need to do? Allow the user to select an image from their phone Enable the user to add a name for the board When the user clicks submit, the entered ...

Uh oh! The dreaded Error [ERR_HTTP_HEADERS_SENT] has struck again in the Node Express MongoDB world. Headers cannot be set after they have

Hey there, newbie in the coding world! I've been diving into a guide on setting up a backend server using Node.js, Express, and MongoDB. You can find the guide here: But I seem to keep running into an error when testing with Postman. Error [ERR_HTTP ...

Dropdown for state selection within WooCommerce for specific countries

I am encountering a challenge in configuring a form with default WooCommerce country and states selection dropdowns. Essentially, my goal is to present the Country selection first, followed by the State selection based on the chosen country. For instance, ...

Modifying npm packages within a web application

I have a web application where I recently installed an npm package. However, I've realized that I need to customize it by adding some code. My attempt to modify the package directly in node_modules hasn't resulted in any visible changes. Is there ...

It vanishes as soon as you move your cursor away during the animation

I created a button component with text animation, but I'm encountering an issue. When I hover over the button, the animation works smoothly. However, if I quickly move my cursor away or unhover in the middle of the animation, the text disappears unex ...

Update nested child object in React without changing the original state

Exploring the realms of react and redux, I stumbled upon an intriguing challenge - an object nested within an array of child objects, complete with their own arrays. const initialState = { sum: 0, denomGroups: [ { coins: [ ...

Troubleshooting: Imported Variable in Angular 2+ Throwing Module Not Found Error

During my testing process, I encountered an issue when trying to require a .json file with data to perform checks on. Despite passing the string indicating where to find the file into the require function, it seems to be unsuccessful... Success: const da ...

Steps to turn off the automatic completion feature for orders in WooCommerce on your WordPress website

Looking for assistance with changing the order status from completed to processing. When an order is placed, it automatically goes to completed status which is not the desired outcome. The status should change based on the virtual product purchased. I wou ...

Is spine.js truly capable of 'streamlining' POST requests?

I recently came across a post by Alex Maccaw, where he discusses the challenges of sending Ajax requests in parallel: Maccaw explains that if a user creates a record and quickly updates it, two Ajax requests are sent simultaneously - a POST and a PUT. How ...