简体   繁体   中英

Updating angular.js service object without extend/copy possible?

I have 2 services and would like to update a variable in the 1st service from the 2nd service. In a controller, I am setting a scope variable to the getter of the 1st service.

The problem is, the view attached to the controller doesn't update when the service variable changes UNLESS I use angular.extend/copy. It seems like I should just be able to set selectedBuilding below without having to use extend/copy. Am I doing something wrong, or is this how you have to do it?

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) {
    ...
    // something happens, gives me a building id
    BuildingsService.setSelectedBuilding(building_id);
    ...
});

Thanks in advance!

I dont believe you need an extend in your service. You should be able to watch the service directly and respond to the changes:

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

More on $watch: https://code.angularjs.org/1.2.16/docs/api/ng/type/$rootScope.Scope

When you execute this code:

$scope.building = BuildingsService.getSelectedBuilding(); 

$scope.building is copied a reference to the same object in memory as your service's selectedBuilding . When you assign another object to selectedBuilding , the $scope.building still references to the old object . That's why the view is not updated and you have to use angular.copy/extend .

You could try the following solution to avoid this problem if you need to assign new objects to your selectedBuilding :

app.factory('BuildingsService', function() {
        var buildingsList = [];
        var building = { //create another object to **hang** the reference
            selectedBuilding : {}
         }
        // buildingsList populated up here
        ...
        var setSelectedBuilding = function(buildingId) {
            //just assign a new object to building.selectedBuilding 
        };
        var getSelectedBuilding = function() {
            return building; //return the building instead of selectedBuilding 
        };
        ...
        return {
            setSelectedBuilding: setSelectedBuilding,
            getSelectedBuilding: getSelectedBuilding    
        }
    });

With this solution, you have to update your views to replace $scope.building bindings to $scope.building.selectedBuilding .

In my opinion, I will stick to angular.copy/extend to avoid this unnecessary complexity.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM