如何在范围之外更改AngularJS数据?

gro*_*190 47 javascript input angularjs

经过几个小时令人沮丧的搜索后,我觉得我需要在这里提交我的问题.如果这个问题在某种程度上得到了回答,我提前道歉,但到目前为止我的搜索都没有帮助.所以这是我的问题:

我的JavaScript代码正在创建一个由AngularJS修改和监视的对象.在某些事件上(比如加载对象的先前设置),我希望从范围外部更改此对象的属性.问题是输入没有改变......

以下是我希望如何执行这些更改的示例:


HTML代码:

<div ng-app="myApp" ng-controller="FirstCtrl">
<input type="number" ng-model="data.age">
<h1>{{data.age}}</h1>

<input type="button" value="Change to 20" ng-model="data" onclick="change()">
Run Code Online (Sandbox Code Playgroud)

JavaScript代码:

var person = {
    age: 16
};

// Create module
var myApp = angular.module('myApp', []);
myApp.factory('Data', function() {
    return person;
});

function FirstCtrl($scope, Data) {
    $scope.data = Data;
}

function change() {
    person.age = 20;
}
Run Code Online (Sandbox Code Playgroud)

当我现在按"更改为20"按钮时,没有任何反应.如何从change功能中修改此人的年龄?

小智 71

⚠️ 警告:此答案陈旧,未反映最佳做法,可能与较新版本的Angular不兼容.

MaxPRafferty的答案是正确的 - 在范围内使用函数通常是更好的方法 - 但还有另一种选择.您可以使用该angular.element(...).scope()方法从不相关的JavaScript访问Angular范围.通过定位具有ng-app指定属性的元素来选择应用程序的顶级范围,例如在您的点击处理程序中:

function change() {
    var appElement = document.querySelector('[ng-app=myApp]');
    var $scope = angular.element(appElement).scope();
    $scope.$apply(function() {
        $scope.data.age = 20;
    });
}
Run Code Online (Sandbox Code Playgroud)

在这个小提琴中尝试一下.

肖恩 刚刚指出,Angular只会在$digest()通话过程中处理任何"手表"或"绑定" .如果您只是$scope直接修改属性,更改可能不会立即反映,您可能会遇到错误.

要触发此操作,您可以调用$scope.$apply()哪个将检查脏范围并更新正确绑定的任何内容.传递执行内部工作的函数$scope.$apply将允许Angular捕获任何异常.Scope的文档中解释了此行为.

  • 不适合我.我的控制器位于具有ng-app的元素的子元素中.这是显示我正在做的事的小提琴:http://jsfiddle.net/jjr5v9Ld/1/ (2认同)

Ale*_*rus 15

Jeremy的回答非常好,虽然现在Angular已经改变了,并且将不再有效,除非你添加这行代码:

$scope = $scope.$$childHead;
Run Code Online (Sandbox Code Playgroud)

因此,更改的函数应如下所示

function change() {
    var appElement = document.querySelector('[ng-app=myApp]');
    var $scope = angular.element(appElement).scope();
    $scope = $scope.$$childHead; // add this and it will work
    $scope.$apply(function() {
        $scope.data.age = 20;
    });
}
Run Code Online (Sandbox Code Playgroud)


Max*_*rty 5

http://jsfiddle.net/MaxPRafferty/GS6Qk/

您希望将ng-click属性设置为范围中的函数,如下所示:

var person = {
    age: 16
};

// Create module
var myApp = angular.module('myApp', []);
myApp.factory('Data', function() {
    return person;
});

function FirstCtrl($scope, Data) {
    $scope.data = Data;
    $scope.update = function(){
        $scope.data.age = 20;
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 5

使用 Jeremy Banks 的完美答案,在一行中完成,但我参考的是控制器与应用程序:

angular.element('[ng-controller=myController]').scope().$apply(function(x){ x.foo = "bar"; });
Run Code Online (Sandbox Code Playgroud)