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

时间:2013-07-15 14:07:36

标签: javascript angularjs input

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

我的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功能修改此人的年龄?

6 个答案:

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

尝试in this Fiddle

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