Aktualisieren Sie die übergeordnete Bereichsvariable in AngularJS

113

Ich habe zwei Controller, einen in einen anderen gewickelt. Jetzt weiß ich, dass der untergeordnete Bereich Eigenschaften vom übergeordneten Bereich erbt. Gibt es jedoch eine Möglichkeit, die übergeordnete Bereichsvariable zu aktualisieren? Bisher habe ich keine offensichtlichen Lösungen gefunden.

In meiner Situation habe ich einen Kalender-Controller in einem Formular. Ich möchte die Start- und Enddaten aus dem übergeordneten Bereich (dem Formular) so aktualisieren, dass das Formular beim Senden die Start- und Enddaten enthält.

Malcr001
quelle
klingt so, als ob Ihr Kalender-Controller eine Direktive sein sollte.
Jonah

Antworten:

192

Sie müssen ein Objekt (kein Grundelement) im übergeordneten Bereich verwenden, und dann können Sie es direkt aus dem untergeordneten Bereich aktualisieren

Elternteil:

app.controller('ctrlParent',function($scope){
    $scope.parentprimitive = "someprimitive";
    $scope.parentobj = {};
    $scope.parentobj.parentproperty = "someproperty";
});

Kind:

app.controller('ctrlChild',function($scope){
    $scope.parentprimitive = "this will NOT modify the parent"; //new child scope variable
    $scope.parentobj.parentproperty = "this WILL modify the parent";
});

Arbeitsdemo : http://jsfiddle.net/sh0ber/xxNxj/

Siehe Was sind die Nuancen der prototypischen / prototypischen Vererbung von Scope in AngularJS?

Dan
quelle
1
Ich erhalte die folgende Fehlermeldung, wenn ich versuche, Folgendes zu implementieren: 'Die Eigenschaft' parentproperty 'von undefined kann nicht festgelegt werden.
Malcr001
Können Sie Ihren Code posten? Es funktioniert in der Geigen-Demo. Wenn Ihr Kalendersteuerelement den isolierten Bereich verwendet, erbt es nicht vom übergeordneten Bereich, sodass Sie den Wert an den Bereich der Direktive übergeben müssen.
Dan
Entschuldigung, ich habe diese Frage vergessen. Ich habe es akzeptiert, weil ich es schließlich geschafft habe, es mit Hilfe dieser Antwort zum Laufen zu bringen.
Malcr001
Ich verstehe, dass das Einfügen von {{parentobj.parentproperty}} in das ctrlParent-div-Element das parentobj-Objekt deklariert und dieses Objekt als im ctrlParent-Bereich befindlich festlegt. Ist das eine richtige Annahme?
Stephane
1
Danke, das funktioniert! Ich sollte dies unbedingt nachlesen (prototypische Vererbung und Primitive). Können Sie eine gute Lektüre empfehlen, die etwas mehr erklärt als Ihr SO-Link?
Jvannistelrooy
116

Es gibt noch eine Möglichkeit, diese Aufgabe auszuführen und die $scope.$parentVariable nicht zu verwenden .

Bereiten Sie einfach eine Methode zum Ändern des Werts im übergeordneten Bereich vor und verwenden Sie sie im untergeordneten Bereich. So was:

app.controller('ctrlParent',function($scope) {
  $scope.simpleValue = 'x';
  $scope.changeSimpleValue = function(newVal) {
    $scope.simpleValue = newVal;
  };
});

app.controller('ctrlChild',function($scope){
    $scope.changeSimpleValue('y');
});

Es funktioniert auch und gibt Ihnen mehr Kontrolle über die Wertänderungen.

Sie können die Methode dann auch in HTML wie folgt aufrufen : <a ng-click="changeSimpleValue('y')" href="#">click me!</a>.

Ravbaker
quelle
1
Gute Lösung! Dies funktioniert, da Angular im $ parent-Bereich nachschlägt, wenn im aktuellen $ -Bereich etwas nicht gefunden wird. docs.angularjs.org/guide/scope (siehe ' Bereichshierarchien ').
Elo
Ich mag diese Antwort, keine Notwendigkeit, ein unnötiges Objekt zu erstellen.
Grimmdude
3
Zukünftige Leser: Alle diese fünf Kommentare sind etwas falsch. Das Erstellen von zwei Setterfunktionen (die "unnötige Objekte" sind) für jede Variable ist ein umständlicher und unnötiger Vererbungsfehler und nicht der Angular-Weg. Misko Hevery, der Schöpfer von Angular, hält einen Vortrag, in dem er lehrt: "Wann immer Sie ein ng-Modell haben, muss irgendwo ein Punkt drin sein. Wenn Sie keinen Punkt haben, machen Sie es falsch." Misko Video @ 29:19
Dan
Wie kann ich diese Lösung mithilfe der ControllerAS-Syntax anwenden?
Niran
6

Dies funktioniert auch (aber nicht sicher, ob dies der Best Practice entspricht oder nicht)

app.controller('ctrlParent',function($scope) {
    $scope.simpleValue = 'x';
});

app.controller('ctrlChild',function($scope){
    $scope.$parent.simpleValue = 'y';
});
DynamicNate
quelle
1
Sie haben Recht, wenn Sie $ scope verwenden. $ Parent.value funktioniert in den meisten Fällen, es ist jedoch normalerweise nicht die beste Idee, es ausgiebig zu verwenden, da es in größeren, komplizierteren Projekten schwierig sein kann, es zu verwalten.
Alex Johnson
4

Wenn Sie einem Bereich ein primitives Attribut zuweisen, ist es immer lokal für den Bereich (möglicherweise im laufenden Betrieb erstellt), auch wenn ein übergeordneter Bereich ein Attribut mit demselben Namen hat. Dies ist eine Designentscheidung und meiner Meinung nach eine gute.

Wenn Sie in der Ansicht ein Grundelement (Ints, Boolesche Werte, Zeichenfolgen) im übergeordneten Bereich ändern müssen, muss es ein Attribut eines anderen Objekts in diesem Bereich sein, damit die Zuweisung möglicherweise lautet:

<a ng-click="viewData.myAttr = 4">Click me!</a>

und es wird wiederum:

  1. Holen Sie sich das viewDataObjekt aus dem Bereich, in dem es definiert ist
  2. Weisen Sie seinem myAttrAttribut 4 zu .
umgeschrieben
quelle
4

Für den Zugriff auf im übergeordneten Element deklarierte Variablen sollten wir $ parent im untergeordneten Controller oder in der Vorlagendatei verwenden

In der Steuerung

$scope.$parent.varaiable_name

In HTML-Vorlage

ng-model="$parent.varaiable_name"
Nibu
quelle