简体   繁体   English

当值在AngularJS之外更改时,AngularJS指令范围不会更新

[英]AngularJS directive scope not updating when value changed outside of AngularJS

I am getting started with AngularJS and have a noob problem that I am not sure how to resolve. 我正在开始使用AngularJS,但有一个菜鸟问题,我不确定该如何解决。 I am modifying a value outside of angular (I have put it in the .run section only for demonstration purposes), and then attempting to run $apply so that Angular will notice that the scope needs to be updated. 我正在修改一个超出angular的值(我仅出于演示目的将其放在.run部分中),然后尝试运行$ apply,以便Angular将注意到需要更新范围。

However, in the following code, the {{currentState}} value gets set to "Initial value" and does not ever update to "Second value". 但是,在以下代码中,{{currentState}}值被设置为“初始值”,并且从未更新为“第二值”。

What is the correct approach to get the value to update? 什么是获取价值更新的正确方法?

angular.module("exampleApp", [])
.run(function(userNotificationService) {
    userNotificationService.setStatus("Initial value");
    setTimeout(function() {
       userNotificationService.setStatus("Second value");
    }, 1000);
})
.factory('userNotificationService', function($rootScope) {
   var currentState = 'Unknown state'; // this should never be displayed
   return {
     setStatus: function(state) {
        $rootScope.$apply(function() {
            currentState = state;
        });
     },
     getStatus: function() {
        return currentState;
     }
  };
}).directive('currentState', function(userNotificationService) {
    return {
        restrict: 'AE',
        scope: false, // set to false so that directive scope is used for transcluded expressions
        link: function(scope) {
            scope.currentState = userNotificationService.getStatus();
        }
    };
}).controller("defaultCtrl", function ($scope) {
// does nothing
});

And the html is the following: html如下:

<body ng-controller="defaultCtrl">
    <div current-state>
        current state: {{ currentState }}
    </div>
</body>

If your use-case involves a timer, then Angular provides its own timer service called $interval which wraps the call in a scope.$apply for you. 如果您的用例涉及一个计时器,那么Angular提供了自己的计时器服务,称为$interval ,它将调用包装在一个scope.$apply为您服务。 You should use that instead of setTimeout . 您应该使用它而不是setTimeout

Now in this case, since you need a one way binding between a service and a value in your scope, you can set up a $watch in your directive: 现在,在这种情况下,由于您需要在服务和作用域中的值之间进行单向绑定,因此可以在指令中设置$watch

 .directive('currentState', function(userNotificationService) {
    return {
        restrict: 'AE',
        scope: false, // set to false so that directive scope is used for transcluded expressions
        link: function(scope) {
            scope.$watch(function () { return userNotificationService.getStatus(); }, function (newVal) {
                scope.currentState = userNotificationService.getStatus();
             });
        }
    };

Ideally how you would do it is by creating this one way (or two way) binding in your controller (which you have left empty). 理想情况下,您将通过在控制器中创建这种单向(或双向)绑定(将其留空)来实现此目的。 The $scope you define on the controller will be available to the directive (if you set $scope: false or $scope: true ), and then you can leave the link function empty. 您在控制器上定义的$scope将可用于该指令(如果将$scope: false$scope: true设置$scope: false ),则可以将link函数保留为空。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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