如何更改范围之外的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,没有任何反应。 我怎样才能从change
function修改人的年龄?
⚠️ 警告:这个答案是旧的,并不反映最佳实践,可能与新版本的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'); }