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

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

我的JavaScript代码正在创build一个对象,由AngularJS修改和监视。 在某些事件上(如加载对象的先前设置),我希望从该范围之外更改此对象的属性。 问题是input不会改变…

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


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()"> 

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; } 

当我现在按“更改为20”button,没有任何反应。 我怎样才能从changefunction修改人的年龄?

⚠️ 警告:这个答案是旧的,并不反映最佳实践,可能与新版本的Angular不兼容。

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

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

试试这个小提琴 。

Shaun 刚刚指出 ,Angular只会在$digest()调用期间处理任何“监视”或“绑定”。 如果您只是直接修改$scope的属性,这些更改可能不会立即反映出来,您可能会收到错误。

要触发这个,你可以调用$scope.$apply()来检查脏的范围,并更新正确绑定的东西。 传递一个在$scope.$apply中执行的函数$scope.$apply将允许Angular捕获任何exception。 此行为在范围的文档中进行了解释。

Jeremy的回答非常好,尽pipe现在Angular已经改变了,并且不再工作,除非你添加下面这行代码:

 $scope = $scope.$$childHead; 

所以,改变的function应该是这样的

 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; }); } 

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; } } 

使用Jeremy Banks的完美答案,尽pipe我引用了控制器和应用程序:

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

只需使用一个简短的$超时

 var whatever = 'xyz'; $timeout(function(){ $scope.yourModel.yourValue = whatever; }, 0); 

你完成了。

我之前尝试过所有这些$应用黑客,他们都没有工作。 但是这个$超时工作总是像一个迷人的,在任何情况下。 所有你需要的是$ scope和$ timeout的引用。

Wy和它是如何工作的:

 // Imagine an angular buildin-function angular.$queue = function(fn){ $timeout(fn, 0); } 

它基本上像一个队列。 但请注意,这是asynchronous的。

使用$ render方法时,如果在指令外修改了值,则由ng-model指令调用。 通过阅读$ viewValue属性来获得新的值。 看: https : //jsfiddle.net/cesar_ade/g5ybs6ne/

 ctrl.$render=function(){ setSelected(ctrl.$viewValue || 'Not Sure'); }