【问题标题】:Update $scope in an $interval function在 $interval 函数中更新 $scope
【发布时间】:2017-11-15 14:29:57
【问题描述】:

我有一个使用angular-material 设计的登录页面。除此之外,我还有一个密码管理器 chrome 扩展程序,它在许多其他网站上运行良好。

我想要实现的是使登录页面与我的密码管理器扩展兼容。扩展提供了字段的id,接下来它获取要插入其中的数据,最后它用获取的值填充输入。这是使用纯 JS 完成的,如下所示:

var inputBox = document.getElementById(fieldId);
if (typeof inputBox !== "undefined" && inputBox !== null) {
    inputBox.click();
    inputBox.focus();
    inputBox.value = fetchedValue;
}

但是,在登录页面上,我有一个显示表单字段的对话框。该扩展能够使用 id 查找字段,也能够插入值。但即使在此之后,required 条件的表单验证错误也会显示出来。

我尝试使用以下代码以角度复制行为:

$scope.user = {
    username: '',
    password: ''
};

$interval(function() {
    var inputBox = document.getElementById("username");
    console.log(inputBox);
    if (typeof inputBox !== "undefined" && inputBox !== null) {
        inputBox.click();
        inputBox.focus();
        inputBox.value = "test";
    }
}, 2000, 1);

username 字段绑定到$scope.user.username,但在插入时,范围仍然没有被修改。

这是复制问题的 JSFiddle:https://jsfiddle.net/prerak6962/fxwmda5w/2/

【问题讨论】:

  • 这不是 Angular 的工作方式。 Angular 使用事件在后台更新$scope 属性;使用 JavaScript 更改输入框的值不会触发事件,因此不会更新角度监控的属性。如果这是在在角度上下文之外完成的,则可以从 angular 调用该函数,后跟 $scope.$apply();但是,如果这是从角度上下文中调用的,例如$interval,那么您必须遵守角度规则,并修改属性,而不是 DOM 值。

标签: javascript angularjs angular-material


【解决方案1】:

为什么不只是:

$interval(function() {
            var inputBox = document.getElementById("username");
            console.log(inputBox);
            if (typeof inputBox !== "undefined" && inputBox !== null) {
                inputBox.focus();
                $scope.user.username = "test";
            }
        }, 2000, 1);

Angular 不会监视输入中的值,而是在您手动更改元素内容时侦听 DOM 事件以跟踪更改 - Angular 永远不会知道某些内容已更改。

附: Angular 是 PLAIN JS。没有“魔法”。例如,这个奇怪的代码会起作用:

var user = {
            username: '',
            password: ''
        };
var rootScope;        

(function() {
    'use strict';
    angular.module('chipsDemo', [])
        .controller('BasicDemoCtrl', DemoCtrl);

    function DemoCtrl($scope, $rootScope) {
        $scope.user = user;
        rootScope = $rootScope;
    }
})();

setInterval(function() {
  user.password = new Date().getTime();
  rootScope.$apply();
}, 1000);

【讨论】:

  • 我想使用纯 JS 更改值,因为我的扩展是使用纯 JS 开发的。我不能使用其他任何东西。我添加了 $interval 部分只是为了使用单个应用程序重现该行为。但实际上有两个不同的应用程序(一个网站和一个 chrome 扩展程序)。
  • 我添加了一些评论,您可以从任何地方轻松操作 Angular 对象。
  • 是的,我读过。但是我的扩展中没有角度。所以我不能在其中使用任何角度服务。
  • 如果你可以运行 js - 你可以。 IE。这将返回任何角度站点的摘要时间(从控制台运行): angular.element(document).injector().invoke(['$rootScope',function($rootScope) { var a = performance.now(); $ rootScope.$apply(); return performance.now()-a; }])
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多