Javascript 与服务值的角度绑定未更新

Javascript 与服务值的角度绑定未更新,javascript,angularjs,Javascript,Angularjs,当绑定服务值被更改时,我无法获取要更新的绑定服务值。我尝试了很多方法,但都没有成功,我做错了什么?从我所看到的一切来看,这似乎应该有效 HTML: 服务: angular.module('worldboxApp'). service('mapService', function(dbService, mapboxService, userService) { this.init = function() { this.activeCountry = {};

当绑定服务值被更改时,我无法获取要更新的绑定服务值。我尝试了很多方法,但都没有成功,我做错了什么?从我所看到的一切来看,这似乎应该有效

HTML:

服务:

angular.module('worldboxApp').
    service('mapService', function(dbService, mapboxService, userService) {

    this.init = function() {
        this.activeCountry = {};
    }

    this.countryClick = function(e) {
        this.activeCountry = e.layer.feature;
    };

    this.init();
});

我设置了一个断点,以确保mapService.activeCountry变量正在更改,但html中显示的所有内容都是
{}

,在某些情况下,$watch不使用factory对象。您可以使用事件进行更新

 app.factory('userService',['$rootScope',function($rootScope){
  var user = {};
  return {

  getFirstname : function () {
    return user.firstname;
  },

  setFirstname : function (firstname) {
    user.firstname = firstname;
    $rootScope.$broadcast("updates");
  }

}
}]);
app.controller('MainCtrl',['userService','$scope','$rootScope', function(userService,$scope,$rootScope) {
  userService.setFirstname("bharat");
  $scope.name = userService.getFirstname();
  $rootScope.$on("updates",function(){
    $scope.name = userService.getFirstname();
  });
}]);

app.controller('one',['userService','$scope', function(userService,$scope) {
  $scope.updateName=function(){
    userService.setFirstname($scope.firstname);
  }
}]);


注意:-在某些情况下,如果未立即触发广播事件,则可以使用$timeout。我在plunker中添加了这一点,时间取决于您的需要。这将适用于工厂和服务。

如果使用范围中的对象及其属性,而不是直接使用字符串/数字/布尔值,则更有可能维护对正确范围的引用

我相信指导原则是,您通常希望在绑定(尤其是ngModel)中有一个“.”(点)——也就是说,
{{data.something}
通常比仅仅
{{something}
要好。如果更新对象上的特性,将保留对父对象的引用,并且可以通过角度查看更新的特性

这通常与您仅在控制器中设置和修改的道具无关,但对于从服务返回的值(可能由服务的多个使用者共享),我发现使用对象很有帮助

请参阅(这些重点是与ngModel绑定的相关性):

angular.module('worldboxApp',[]);
/*控制器*/
角度。模块('worldboxApp')
.controller('DrawerController',['$scope','mapService',
功能($scope,mapService){
//映射到对象(按ref)而不仅仅是字符串(按val),否则很容易丢失引用
$scope.data=mapService.data;
$scope.setCountry=setCountry;//见下文
功能设置国家/地区(国家/地区){
//可以只设置$scope.setCountry=mapService.setCountry;
//但是,如果我们想做一些不太一般的事情,我们可以将其包装在这里
//就像从事件对象中获取数据,然后再将其传递给
//服务。
mapService.setCountry(国家);
}
}
]);
/*服务*/
角度。模块('worldboxApp')
.service('mapService',['$log',
函数($log){
var self=this;//这样函数就可以引用.data;函数中的“this”将不会到达正确的范围
self.data={
活动国家/地区:空
};//我们使用对象,因为它可以通过引用返回,更改activeCountry的值不会中断它与使用它的控制器之间的链接
_init();
函数_init(){
self.data.activeCountry='';
$log.log('Init被调用!');
}
this.setCountry=函数_setCountry(国家){
$log.log('setCountry被称为:'+country);
self.data.activeCountry=国家/地区;
}
}
]);

美国

澳大利亚
活动国家:{{data.activeCountry}
从技术上讲,这是可行的,但在触发事件时,我没有得到新值,只有一个空对象仍然存在。就像控制器中注入的mapService是原始mapService的不同实例一样。我认为服务基本上是单例的,但我的结果表明不是这样。我只是用你的方法解决了这个问题,并将服务更改为工厂。我想我没有正确理解两者之间的区别。谢谢你的帮助。很高兴帮助你。干得好,我想我明白了。因此,如果我不返回函数并仍然尝试使用它,它基本上是原始函数的一个实例,而不是“静态的”?我假设整个服务将作为一个单例,不管我返回了什么。嗨,Nate,抱歉-你的假设没有错,我的回答不清楚,包括了更多风格上的变化/建议,而不是解决问题的具体建议。我进行了编辑以尝试澄清,并以更类似的方式实现了该服务。基本上,我认为关键的区别在于返回并处理对象及其属性,这有助于防止引用中断,因为最终可能指向错误的作用域。我现在明白了,但如果不使用巴拉特建议的广播,我仍然无法更新数据。然而,这两个答案的结合解决了我的问题。
angular.module('worldboxApp').
    service('mapService', function(dbService, mapboxService, userService) {

    this.init = function() {
        this.activeCountry = {};
    }

    this.countryClick = function(e) {
        this.activeCountry = e.layer.feature;
    };

    this.init();
});
 app.factory('userService',['$rootScope',function($rootScope){
  var user = {};
  return {

  getFirstname : function () {
    return user.firstname;
  },

  setFirstname : function (firstname) {
    user.firstname = firstname;
    $rootScope.$broadcast("updates");
  }

}
}]);
app.controller('MainCtrl',['userService','$scope','$rootScope', function(userService,$scope,$rootScope) {
  userService.setFirstname("bharat");
  $scope.name = userService.getFirstname();
  $rootScope.$on("updates",function(){
    $scope.name = userService.getFirstname();
  });
}]);

app.controller('one',['userService','$scope', function(userService,$scope) {
  $scope.updateName=function(){
    userService.setFirstname($scope.firstname);
  }
}]);