AngularJS从控制器触发并监视对象值的服务变化

sat*_*hvj 35 watch angularjs

我正试图从控制器中观察服务的变化.我在stackoverflow上尝试了很多基于很多qns的东西,但我一直无法使它工作.

HTML:

<div ng-app="myApp">
    <div ng-controller="MyCtrl">
        <div ng-click="setFTag()">Click Me</div>
    </div> 
</div>
Run Code Online (Sandbox Code Playgroud)

JavaScript的:

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

myApp.service('myService', function() {
    this.tags = {
        a: true,
        b: true
    };


    this.setFalseTag = function() {
        alert("Within myService->setFalseTag");
        this.tags.a = false;
        this.tags.b = false;

        //how do I get the watch in MyCtrl to be triggered?
    };
});


myApp.controller('MyCtrl', function($scope, myService) {

    $scope.setFTag = function() {
        alert("Within MyCtrl->setFTag");
        myService.setFalseTag();
    };        

    $scope.$watch(myService.tags, function(newVal, oldVal) {
        alert("Inside watch");
        console.log(newVal);
        console.log(oldVal);
    }, true);

});
Run Code Online (Sandbox Code Playgroud)

如何让手表在控制器中触发?

的jsfiddle

Max*_*tin 75

尝试$watch用这种方式写:

myApp.controller('MyCtrl', function($scope, myService) {


    $scope.setFTag = function() {
       myService.setFalseTag();
    };        

    $scope.$watch(function () {
       return myService.tags;
     },                       
      function(newVal, oldVal) {
        /*...*/
    }, true);

});
Run Code Online (Sandbox Code Playgroud)

演示 Fiddle

[编辑]

有时这种方式不起作用,特别是如果服务已从3d方更新.

为了使它工作,我们必须帮助角度消防摘要周期.

这是一个例子:

在服务方面,当我们想要更新tags值时写下如下内容:

if($rootScope.$root.$$phase != '$apply' && $rootScope.$root.$$phase != '$digest'){
   $rootScope.$apply(function() {
     self.tags = true;
   });
 }
 else {
   self.tags = true;
  }
Run Code Online (Sandbox Code Playgroud)

  • 我不知道你能以这种方式使用手表.这是一个改变游戏规则的游戏.如此多的胜利. (11认同)
  • @Phill我只添加了其他测试用例:如果你使用的例如Cordova插件超出了角度范围,那么观察者就无法工作了.人们可能会复制/粘贴此示例,并会惊讶为什么它不起作用.所以我试着涵盖不同的案例 (2认同)