【问题标题】:AngularJS Input field not updating from setTimeout inside controllerAngularJS输入字段未从控制器内的setTimeout更新
【发布时间】:2015-06-25 11:46:22
【问题描述】:

我正在使用 AngularJS 驱动的页面,我需要在只读输入文本字段内显示一个运行时钟(与 data-ng-model) 绑定的两种方式。为了模拟运行时钟,我使用了一个 JavaScript 调度程序setTimeout 每 1000 毫秒调用一个函数,它会更新 $scope 的属性值,该属性值又绑定到该输入文本字段。不知何故,输入字段中的值没有得到更新。所以我放置了一个 <pre />标记并使用 jQuery 选择器更新其内容。这工作正常,所以我需要帮助获取输入文本字段值,以便每秒更新一次。

我为此示例设置了jsFiddle

HTML 如下:

<body data-ng-app="formApp">
    <div data-ng-controller="FormCtrl">
        Current Date and Time <input type="text" data-ng-model="formData.currentDateTime" readonly="readonly" size="60" />
    </div>
    <pre id="currentDateTime" style="font-size:1.5em;">
    </pre>
</body>

AngularJS 应用模块和控制器声明如下:

(function() {
    var formApp = angular.module("formApp", []);

    formApp.controller("FormCtrl", function ($scope) {
        $scope.formData = {};
        $scope.formData.currentDateTime = new Date().toString();

        (function updateCDT() {
            $scope.formData.currentDateTime = new Date().toString();
            document.getElementById("currentDateTime").innerHTML = $scope.formData.currentDateTime;
            setTimeout(updateCDT, 1000);
        })();
    });
})();

【问题讨论】:

    标签: javascript jquery html angularjs settimeout


    【解决方案1】:

    您需要使用 $scope.$apply() 或 angulars $timeout 来反映更改,因为 setTimeout 超出了 angularjs 的范围

    使用 $scope.$apply()

    在 setTimeout(function(){},1000) 的匿名函数中应用 $scope.$apply(),然后像下面这样调用实际函数

       (function updateCDT() {
            $scope.formData.currentDateTime = new Date().toString();
            document.getElementById("currentDateTime").innerHTML
      = $scope.formData.currentDateTime;
            setTimeout(function(){
              $scope.$apply();
                updateCDT()
            }, 1000);
    

    fiddle 用于 $scope.$apply()

    使用 $timeout(不要忘记将其注入控制器)

     (function updateCDT() {
                $scope.formData.currentDateTime = new Date().toString();
                document.getElementById("currentDateTime").innerHTML
        = $scope.formData.currentDateTime;
                $timeout(updateCDT, 1000);
              
            })();
    

    fiddle $timeout

    【讨论】:

    • 我将$timeout注入控制器并使用它,因为它看起来更干净因为Chrome开发工具在使用$scope.$apply();时显示错误Error: [$rootScope:inprog] $apply already in progress。感谢您的即时帮助!
    【解决方案2】:

    只需和 pre 标签中的一样:

    document.getElementById("input-field").value=$scope.formData.currentDateTime;
    

    希望对你有帮助!

    【讨论】:

    • 我想我可以这样做,但我想用 AngularJS 的方式来做 :-) 谢谢你的建议。
    【解决方案3】:

    您可以使用$timeout() 而不是使用setTimeout(),它会在内部调用$apply(),从而告诉angular 运行摘要。

    记得注入 $timeout 作为依赖项

    DEMO

    【讨论】:

      【解决方案4】:

      如果您使用 setTimeout 修改 Angular 之外的范围,则需要调用 $scope.$apply

      【讨论】:

      • Chrome 开发者工具在使用$scope.$apply(); 时显示错误Error: [$rootScope:inprog] $apply already in progress,所以我选择了$timeout
      • @WebUser 你可以使用if(!$scope.$$phase) { //call $apply }
      • @WebUser 或者您可以在 setTimeout(function(){ $scope.$apply(); updateCDT()},1000) 的匿名函数中应用 $scope.$apply() 然后调用实际功能
      猜你喜欢
      • 2013-09-02
      • 2017-10-09
      • 1970-01-01
      • 2012-04-03
      • 2016-02-27
      • 1970-01-01
      • 1970-01-01
      • 2016-08-27
      • 2015-12-01
      相关资源
      最近更新 更多