简体   繁体   中英

angularjs: controllers not sharing data, using a service

I have these controllers and service:

  angular.module('myApp', []);

  angular.module('myApp').factory('ShareService', function() {
    var delivery = {};
    delivery.name = "";
    delivery.setName = function(n){
      delivery.name = n;
    }
    return delivery;
  });


  angular.module('myApp').controller('controller2', function (ShareService) {
    this.name = ShareService.name;
  });


  angular.module('myApp').controller('controller1', function (ShareService) {
    this.setName = function (){
      ShareService.setName ("any name");
    };
  });

and the html:

<body ng-controller="controller1 as ctrl1">

 <button ng-click="ctrl1.setName()">Click Me</button>

 <div ng-controller="controller2 as ctrl2">
   <input type="text" ng-model="ctrl2.name">
 </div>

</body>

Why clicking the button doesn't update the input with the text "any name" What's wrong here? I have no clue. Thanks!

You are running into an issue with the difference between copied by value vs copied by reference.

Particularly, this line of code:

this.name = ShareService.name;

Means you are actually copying the value of ShareService.name but not the actual reference to it because it is a primitive.

If you really want to share the exact same value, then you need a reference to an object, instead of the primitive value. You could bind directly to the ShareService instance if you wanted:

this.shareService = ShareService;

ng-model="ctrl2.shareService.name"

But that feels a little funny to me.

Another alternative is to create a "model" object of some kind on your ShareService and copy a reference to that into your controller instead.

var delivery = {
   shared: {name:""}
};

delivery.setName = function(n){
  delivery.shared.name = n;
}
return delivery;

this.shared = ShareService.shared;

ng-model="ctrl2.shared.name"

This would all have the effect of making sure that the bound property is always pointing to the same shared value, and not just a copy.

Here is a plunker with a working example: http://plnkr.co/edit/i5jPFl717RtkMw0MwVTZ?p=preview

The thing is that this.name = ShareService.name; is copying by value and not by reference.

A workaround could be to define your delivery.name as an Object and not as a string. So that you can copy it by reference.

app.factory('ShareService', function() {
  var delivery = {};
  delivery.name = {
    value: "default"
  };
  delivery.setName = function(n) {
    delivery.name.value = n;
  }
  return delivery;
});

app.controller('controller1', function(ShareService) {
  this.setName = function() {
    ShareService.setName("modified");
  };
});

app.controller('controller2', function(ShareService) {
  this.name = ShareService.name;
});

Then you could use it like this:

<div ng-controller="controller2 as ctrl2">
    <input type="text" ng-model="ctrl2.name.value">
  </div>

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