Angularjs, Passing Scope zwischen Routen

87

Ich habe eine Situation mit einem Formular, das sich über mehrere Seiten erstreckt (möglicherweise nicht ideal, aber so ist es). Ich möchte einen Bereich für das gesamte Formular haben, der im Laufe der Zeit ausgefüllt wird, damit der Benutzer sich leicht an den Status erinnert, wenn er zwischen den Schritten hin und her geht.

Also muss ich in sehr Pseudo-Code tun:

  1. einstellen $scope.val = <Some dynamic data>
  2. Klicken Sie auf einen Link und lassen Sie sich zu einer neuen Vorlage weiterleiten (wahrscheinlich mit demselben Controller).
  3. $scope.val sollte immer noch den gleichen Wert haben wie auf der letzten Seite.

Sind persistente Daten für den Bereich der richtige Weg, um dies zu erreichen, oder gibt es einen anderen Weg? Können Sie sogar einen Controller erstellen, der einen dauerhaften Bereich zwischen Routen hat, außer natürlich in einer Datenbank zu speichern?

Erik Honn
quelle
Nur als Ergänzung zu Ganaraj: Hier finden Sie einen wirklich schönen Blogeintrag mit einem Screencast darüber, wie Sie verschiedene Controller zur Kommunikation bringen können. Es gibt auch ein paar hilfreiche Jsfiddles, mit denen man herumspielen kann. onehungrymind.com/angularjs-communicating-between-controllers Ich hoffe, es hilft.
F Lekschas

Antworten:

138

Sie müssen einen Dienst verwenden, da ein Dienst während der gesamten Lebensdauer Ihrer App bestehen bleibt.

Nehmen wir an, Sie möchten Daten eines Benutzers speichern

So definieren Sie den Service:

app.factory("user",function(){
        return {};
});

In Ihrem ersten Controller:

app.controller( "RegistrationPage1Controller",function($scope,user){
    $scope.user = user;
    // and then set values on the object
    $scope.user.firstname = "John";
    $scope.user.secondname = "Smith";
});

app.controller( "RegistrationSecondPageController",function($scope,user){
        $scope.user = user;
        // and then set values on the object
        $scope.user.address = "1, Mars";

    });
Ganaraj
quelle
6
Ähhh! Ich habe das zuvor versucht, konnte es aber nicht zum Laufen bringen, da ich für beide Routen denselben Controller verwendet habe. Bei jeder neuen Route überschreiben die Standardwerte die Werte, die ich auf der vorherigen Seite eingegeben habe. Bei zwei Controllern oder ohne Standardwerte ist dies nicht mehr der Fall. Vielen Dank!
Erik Honn
1
Was ist mit Value Recipe docs.angularjs.org/guide/providers , wie myApp.value('clientId', 'a12345654321x');ist das auch zwischen den Routen beständig?
Die Bndr
@ TheBndr: Es sollte sein. Werte sind nach meinem Verständnis nur eine besondere Form von Dienstleistungen.
Robert Koritnik
3
Dienste bleiben keine Daten erhalten, wenn Sie die Seite neu laden ... Wenn Sie sich also auf Seite 4 Ihres Formulars befinden und diese Seite neu laden, verlieren Sie alle ausgefüllten Daten.
Danielrvt
1
Gute Antwort! Als Nebeneffekt sollte ein Styleguide für diejenigen, die diese Antwort übernehmen - Services, die selbst keine Konstruktoren sind (dh als neue XX verwendet werden), als Kamel in Kleinbuchstaben bezeichnet werden: github.com/mgechev/angularjs-style-guide .
Matt Byrne
9

Der Dienst wird funktionieren, aber eine logische Methode, um nur normale Bereiche und Controller zu verwenden, besteht darin, Ihre Controller und Elemente so einzurichten, dass sie die Struktur Ihres Modells widerspiegeln. Insbesondere benötigen Sie ein übergeordnetes Element und einen Controller, die einen übergeordneten Bereich festlegen. Die einzelnen Seiten des Formulars sollten sich in einer Ansicht befinden, die dem Elternteil untergeordnet ist. Der übergeordnete Bereich bleibt bestehen, auch wenn die untergeordnete Ansicht aktualisiert wird.

Ich gehe davon aus, dass Sie einen UI-Router verwenden, damit Sie benannte benannte Ansichten haben können. Dann im Pseudocode:

<div ng-controller="WizardController">
  <div name="stepView" ui-view/>
</div>

Anschließend definiert WizardController die Bereichsvariablen, die Sie in den Schritten des mehrseitigen Formulars (das ich als "Assistent" bezeichne) beibehalten möchten. Dann werden stepViewnur Ihre Routen aktualisiert . Jeder Schritt kann seine eigenen Vorlagen, Controller und Bereiche haben, aber ihre Bereiche gehen von Seite zu Seite verloren. Die Bereiche in WizardController bleiben jedoch auf allen Seiten erhalten.

Um die WizardController-Bereiche von den untergeordneten Controllern aus zu aktualisieren, müssen Sie für jede Bereichsvariable $scope.$parent.myProp = 'value'eine Syntax wie oder eine Funktion setMyPropin WizardController definieren. Wenn Sie andernfalls versuchen, die übergeordneten Bereichsvariablen direkt über die untergeordneten Controller festzulegen, erstellen Sie am Ende nur eine neue Bereichsvariable für das untergeordnete Steuerelement selbst und schattieren die übergeordnete Variable.

Etwas schwer zu erklären und ich entschuldige mich für das Fehlen eines vollständigen Beispiels. Grundsätzlich möchten Sie einen übergeordneten Controller, der einen übergeordneten Bereich erstellt, der auf allen Seiten Ihres Formulars beibehalten wird.

tksfz
quelle
1
Dies würde ja mit UI-Router funktionieren (und es ist eine ziemlich gute Möglichkeit, eine solche Seite zu entwerfen), aber nicht sofort einsatzbereit. Die Servicemethode ist sofort einsatzbereit.
Erik Honn
1
Zur Verdeutlichung werden die Eigenschaften des übergeordneten Bereichs immer vom untergeordneten Bereich übernommen. Wenn Sie jedoch eine übergeordnete Bereichseigenschaft aus dem untergeordneten Bereich festlegen möchten, müssen Sie auf den übergeordneten Bereich zugreifen, andernfalls erstellen Sie eine neue gleichnamige Eigenschaft im untergeordneten Bereich. Das Festlegen einer übergeordneten Scope-Eigenschaft kann folgendermaßen erfolgen:$scope.$parent.myProp = 'hello world';
mbursill
1
Dies ist ein viel besserer Ansatz als die Verwendung eines Dienstes. Dienste sind Singletons, daher ist jeder dort definierte Status für die Anwendung global. Wenn der Benutzer den Assistenten teilweise beendet und dann neu startet, verbleibt im Status des vorherigen Laufs ein Reststatus - es sei denn, Sie stellen sicher, dass Sie den Dienst an jedem Beendigungspunkt ordnungsgemäß bereinigen, dies kann jedoch durchaus möglich sein leicht zu einem erheblichen Wartungskopfschmerz werden!
Dan King
Viel mehr an dieser Antwort interessiert
Kurai Bankusu
Dienste sind das erste, was Ihnen in den Sinn kommt, wenn Sie den Angular UI Router nicht verwenden. Wenn Sie jedoch UI Router verwenden, hat es verschachtelte Auflösungen, die Informationen zwischen verschachtelten Ansichten beibehalten können. Ich denke, das wäre ein sauberer Ansatz als der Versuch, auf den übergeordneten Bereich zuzugreifen. medium.com/opinionated-angularjs/…
losmescaleros
5

Die Daten können auf zwei Arten zwischen Controllern übertragen werden

  1. $rootScope
  2. Modell

Das folgende Beispiel zeigt die Übergabe von Werten mithilfe des Modells

app.js.

angular.module('testApp')
  .controller('Controller', Controller)
  .controller('ControllerTwo', ControllerTwo)
  .factory('SharedService', SharedService);

SharedService.js

function SharedService($rootScope){

 return{
    objA: "value1",
    objB: "value2"
  }
}

// Ändern Sie den Wert in Controller A.

Controller.js

function Controller($scope, SharedService){

 $scope.SharedService = SharedService;

 $scope.SharedService.objA = "value1 modified";
}

// Zugriff auf den Wert in controllerertwo

ControllerTwo.js

function ControllerTwo($scope, SharedService){

 $scope.SharedService = SharedService;

 console.log("$scope.SharedService.objA"+$scope.SharedService.objA); // Prints "value1 modified"
}

Hoffe das hilft.

DILIP KOSURI
quelle