簡體   English   中英

如何在范圍之外更改AngularJS數據?

[英]How to change AngularJS data outside the scope?

經過幾個小時令人沮喪的搜索后,我覺得我需要在這里提交我的問題。 如果這個問題在某種程度上得到了回答,我提前道歉,但到目前為止我的搜索都沒有幫助。 所以這是我的問題:

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

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

⚠️ 警告:此答案陳舊,未反映最佳做法,可能與較新版本的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 剛剛指出 Angular只會在$digest()調用期間處理任何“監視”或“綁定”。 如果您只是直接修改$scope的屬性,則可能不會立即反映更改,您可能會遇到錯誤。

要觸發這個,你可以調用$scope.$apply()來檢查臟范圍並更新任何正確綁定的東西。 傳遞一個在$scope.$apply內執行工作的函數$scope.$apply將允許Angular捕獲任何異常。 Scope的文檔中解釋了此行為。

Jeremy的回答非常好,雖然現在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;
    });
}

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的完美答案,在一行中完成,雖然我引用了控制器與應用程序:

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

只需使用短暫的$ 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);
}

它基本上像一個隊列。 但要注意它是異步的。

當在指令之外修改了值時,ng-model指令調用$ render方法。 通過讀取$ viewValue屬性獲取新值。 看: https//jsfiddle.net/cesar_ade/g5ybs6ne/

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM