webentwicklung-frage-antwort-db.com.de

Wie kann man AngularJS-Daten außerhalb des Gültigkeitsbereichs ändern?

Nach stundenlangen frustrierenden Recherchen muss ich meine Frage hier einreichen. Ich entschuldige mich im Voraus, wenn diese Frage vorher irgendwie beantwortet wurde, aber bisher keine meiner Suchvorgänge geholfen hat. Also hier meine Frage:

Mein JavaScript-Code erstellt ein Objekt, das von AngularJS geändert und überwacht wird. Bei einigen Ereignissen (wie dem Laden einer vorherigen Einstellung des Objekts) möchte ich die Eigenschaften dieses Objekts von außerhalb des Bereichs ändern. Das Problem ist, dass sich die Eingänge nicht ändern ...

Hier ein Beispiel, wie ich diese Änderungen durchführen möchte:


HTML Quelltext:

<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-Code:

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

Wenn ich jetzt die Schaltfläche "Change to 20" drücke, passiert nichts. Wie kann ich das Alter der Person von der Funktion change ändern?

44
gromit190

⚠️ Warnung: Diese Antwort ist alt, spiegelt keine bewährten Methoden wider und ist möglicherweise nicht mit neueren Versionen von Angular kompatibel. 

Die Antwort von MaxPRafferty ist richtig - die Verwendung einer Funktion im Geltungsbereich ist oft der schönere Weg, dies zu tun - aber es gibt eine andere Option. Sie können die angular.element(...).scope()-Methode verwenden, um über nicht zusammenhängendes JavaScript auf einen Angular-Bereich zuzugreifen. Wählen Sie den Bereich der obersten Ebene für die App aus, indem Sie auf das Element abzielen, für das das ng-app-Attribut angegeben ist. Etwa in Ihrem Click-Handler:

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

Probieren Sie es aus in dieser Fiddle .

Shaunnur darauf hingewiesen dass Angular nur "Watches" oder "Bindings" während eines Aufrufs von $digest() verarbeitet. Wenn Sie nur die Eigenschaften von $scope direkt ändern, werden die Änderungen möglicherweise nicht sofort übernommen und Sie erhalten möglicherweise Fehler.

Um dies auszulösen, können Sie $scope.$apply() aufrufen, das auf fehlerhafte Bereiche prüft und alles korrekt aktualisiert. Wenn Sie eine Funktion übergeben, die die Arbeit in $scope.$apply erledigt, kann Angular auch Ausnahmen abfangen. Dieses Verhalten wird in der Dokumentation zu Scope erklärt.

71
Jeremy Banks

Jeremys Antwort ist wirklich gut, obwohl sich Angular jetzt geändert hat und nicht mehr funktioniert, es sei denn, Sie fügen diese Codezeile hinzu:

$scope = $scope.$$childHead;

Die geänderte Funktion sollte also so aussehen

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

http://jsfiddle.net/MaxPRafferty/GS6Qk/

Sie möchten Ihr ng-click-Attribut wie folgt auf eine Funktion in Ihrem Bereich setzen:

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

Verwenden Sie einfach ein kurzes $ Timeout

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

und du bist fertig.

Ich habe alle diese $ -Hacks aus dem gesamten World Wide Web ausprobiert und sie funktionierten nicht. Dieses $ timeout funktioniert jedoch immer wie ein Charme und in jedem Fall ... __ Sie benötigen lediglich einen Verweis auf Ihren $ scope und $ timeout.

Wy und wie es funktioniert:

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

Es funktioniert im Grunde wie eine Warteschlange. Seien Sie sich jedoch bewusst, dass es asynchron ist.

3
Steffomio

Mit Jeremy Banks 'perfekter Antwort in einer Zeile, obwohl ich mich auf den Controller und die App beziehe:

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

Mit der $ render-Methode wird die ng-model-Direktive aufgerufen, wenn der Wert außerhalb der Direktive geändert wurde. Erhalten Sie einen neuen Wert, indem Sie die $ viewValue-Eigenschaft lesen. Schauen Sie: https://jsfiddle.net/cesar_ade/g5ybs6ne/

ctrl.$render=function(){
    setSelected(ctrl.$viewValue || 'Not Sure');
}
0
César Alcívar