经过几个小时令人沮丧的搜索后,我觉得我需要在这里提交我的问题。如果这个问题在某种程度上得到了回答,我提前道歉,但到目前为止我的搜索都没有帮助。所以这是我的问题:
我的JavaScript代码正在创建一个由AngularJS修改和监控的对象。在某些事件上(比如加载对象的先前设置),我希望从范围外部更改此对象的属性。问题是输入没有改变......
以下是我希望如何执行这些更改的示例:
HTML code:
<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”按钮时,没有任何反应。如何从change
功能修改此人的年龄?
答案 0 :(得分: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;
});
}
Shaun just pointed out Angular只会在$digest()
来电期间处理任何“观看”或“绑定”。如果您只是直接修改$scope
的属性,则更改可能不会立即反映出来,您可能会遇到错误。
要触发此操作,您可以调用$scope.$apply()
来检查脏范围并更新任何正确绑定的内容。传递一个在$scope.$apply
内完成工作的函数将允许Angular捕获任何异常。 the documentation for Scope中解释了此行为。
答案 1 :(得分:14)
Jeremy's answer非常好,虽然现在Angular已经改变了,并且将不再有效,除非你添加这行代码:
$scope = $scope.$$childHead;
因此,更改的函数应如下所示
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;
});
}
答案 2 :(得分: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;
}
}
答案 3 :(得分:3)
使用Jeremy Banks&#39;完美的答案,完成一行,虽然我引用了控制器与应用程序:
angular.element('[ng-controller=myController]').scope().$apply(function(x){ x.foo = "bar"; });
答案 4 :(得分:3)
只需使用短暂的$ timeout
var whatever = 'xyz';
$timeout(function(){
$scope.yourModel.yourValue = whatever;
}, 0);
你已经完成了。
我之前尝试过围绕www的所有那些$ apply hacks,他们都没有工作。但是这个$ timeout在每种情况下总是像魅力一样。 您只需要引用$ scope和$ timeout。
Wy及其运作方式:
// Imagine an angular buildin-function
angular.$queue = function(fn){
$timeout(fn, 0);
}
它基本上像一个队列。但要注意它是异步的。
答案 5 :(得分:0)
当在指令之外修改了值时,ng-model指令调用$ render方法。通过读取$ viewValue属性获取新值。看:https://jsfiddle.net/cesar_ade/g5ybs6ne/
ctrl.$render=function(){
setSelected(ctrl.$viewValue || 'Not Sure');
}