Angularjs, przekazywanie zakresu między trasami

87

Mam sytuację z formularzem, który rozciąga się na kilka stron (może nie jest idealny, ale tak właśnie jest). Chciałbym mieć jeden zakres dla całego formularza, który jest wypełniany w miarę postępów, aby użytkownik mógł łatwo zapamiętać stan, gdy użytkownik przechodzi między krokami.

Muszę więc zrobić w bardzo pseudokodzie:

  1. Zestaw $scope.val = <Some dynamic data>
  2. Kliknij łącze i przejdź do nowego szablonu (prawdopodobnie z tym samym kontrolerem).
  3. $scope.val Powinien nadal mieć tę samą wartość, co na ostatniej stronie.

Czy w jakiś sposób utrwalanie danych dla zakresu jest właściwym sposobem rozwiązania tego problemu, czy jest inny sposób? Czy możesz nawet utworzyć kontroler, który ma trwały zakres między trasami, z wyjątkiem oczywiście zapisywania go w bazie danych.

Erik Honn
źródło
Podobnie jak dodatek do ganaraj: tutaj znajdziesz naprawdę fajny wpis na blogu z screencastem na temat tego, jak zmusić różne kontrolery do komunikacji. Istnieje również kilka przydatnych plików jsfiddles do zabawy. onehungrymind.com/angularjs-communicating-between-controllers Mam nadzieję, że to pomoże.
F Lekschas,

Odpowiedzi:

138

Musisz skorzystać z usługi, ponieważ usługa będzie trwać przez cały okres użytkowania aplikacji.

Powiedzmy, że chcesz zapisać dane dotyczące użytkownika

Tak definiujesz usługę:

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

W swoim pierwszym kontrolerze:

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
źródło
6
Ahhh! Próbowałem tego wcześniej, ale nie mogłem go uruchomić, ponieważ użyłem tego samego kontrolera dla obu tras, więc przy każdej nowej trasie wartości domyślne nadpisywały te, które wprowadziłem na poprzedniej stronie. W przypadku dwóch kontrolerów lub bez wartości domyślnych to się już nie dzieje. Dzięki!
Erik Honn,
1
O co chodzi z Value Recipe docs.angularjs.org/guide/providers , czy myApp.value('clientId', 'a12345654321x');jest to również trwałe między trasami?
Bndr
@TheBndr: Powinno być. Wartości są po prostu specjalną formą usług, jak to rozumiem.
Robert Koritnik,
3
Usługi nie będą utrwalać danych, jeśli ponownie załadujesz stronę ... Więc jeśli jesteś na stronie 4 swojego formularza i ponownie załadujesz tę stronę, utracisz wszystkie wypełnione dane.
danielrvt
1
Niezła odpowiedź! Na marginesie, przewodnik po stylu dla tych, którzy przyjmują tę odpowiedź - usługi, które same nie są konstruktorami (tj. Używane jako nowy XX), powinny zostać nazwane małymi literami camel: github.com/mgechev/angularjs-style-guide .
Matt Byrne,
9

Usługa będzie działać, ale logicznym sposobem na zrobienie tego przy użyciu tylko zwykłych zakresów i kontrolerów jest skonfigurowanie kontrolerów i elementów tak, aby odzwierciedlały strukturę Twojego modelu. W szczególności potrzebny jest element nadrzędny i kontroler, które ustanawiają zakres nadrzędny. Poszczególne strony formularza powinny znajdować się w widoku będącym dzieckiem rodzica. Zakres nadrzędny utrzymuje się nawet po zaktualizowaniu widoku podrzędnego.

Zakładam, że używasz routera ui, więc możesz mieć zagnieżdżone nazwane widoki. Następnie w pseudokodzie:

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

Następnie WizardController definiuje zmienne zakresu, które chcesz zachować na kolejnych etapach wielostronicowego formularza (który nazywam „kreatorem”). Wtedy Twoje trasy zostaną zaktualizowane stepView. Każdy krok może mieć własne szablony, kontrolery i zakresy, ale ich zakresy są tracone ze strony na stronę. Ale zakresy w WizardController są zachowywane na wszystkich stronach.

Aby zaktualizować zakresy WizardController z kontrolerów podrzędnych, musisz użyć składni takiej jak $scope.$parent.myProp = 'value'lub zdefiniować funkcję setMyPropw WizardController dla każdej zmiennej zakresu. W przeciwnym razie, jeśli spróbujesz ustawić zmienne zakresu nadrzędnego bezpośrednio z kontrolerów podrzędnych, w końcu utworzysz nową zmienną zakresu na samym dziecku, cieniując zmienną nadrzędną.

Trochę trudne do wyjaśnienia i przepraszam za brak pełnego przykładu. Zasadniczo potrzebujesz kontrolera nadrzędnego, który ustanawia zakres nadrzędny, który zostanie zachowany na wszystkich stronach formularza.

tksfz
źródło
1
To działałoby z routerem ui tak (i ​​jest to całkiem niezły sposób na zaprojektowanie takiej strony), ale nie po wyjęciu z pudełka. Po wyjęciu z pudełka metoda obsługi jest drogą do zrobienia.
Erik Honn
1
Gwoli wyjaśnienia, właściwości zakresu nadrzędnego zawsze będą dziedziczone przez zakres podrzędny. Jeśli jednak chcesz ustawić właściwość zakresu nadrzędnego z zakresu podrzędnego, musisz uzyskać do niej dostęp w zakresie nadrzędnym, w przeciwnym razie tworzysz nową właściwość o tej samej nazwie w zakresie podrzędnym. Ustawienie właściwości zasięgu nadrzędnego można wykonać, przechodząc do:$scope.$parent.myProp = 'hello world';
mbursill
1
To o wiele przyjemniejsze podejście niż korzystanie z usługi. Usługi są singletonami, więc każdy zdefiniowany tam stan ma charakter globalny dla aplikacji. Jeśli użytkownik wyjdzie z kreatora w części, a następnie uruchomi go ponownie, w usłudze pozostanie stan pozostałości z poprzedniego uruchomienia - chyba że upewnisz się, że prawidłowo wyczyścisz usługę w każdym punkcie wyjścia, ale może to całkiem łatwo stać się poważnym bólem głowy związanym z konserwacją!
Dan King
O wiele bardziej chętni do tej odpowiedzi
Kurai Bankusu
Usługi są pierwszą rzeczą, która przychodzi Ci do głowy, jeśli nie używasz routera Angular UI Router. Jeśli jednak używasz routera UI, ma on zagnieżdżone rozwiązania, które mogą utrwalać informacje między zagnieżdżonymi widokami. Myślę, że byłoby to czystsze podejście niż próba uzyskania dostępu do zakresu nadrzędnego. medium.com/opinionated-angularjs/…
losmescaleros
5

Dane mogą być przekazywane między administratorami na dwa sposoby

  1. $rootScope
  2. Model

Poniższy przykład ilustruje przekazywanie wartości za pomocą modelu

app.js

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

SharedService.js

function SharedService($rootScope){

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

// Zmodyfikuj wartość w kontrolerze A

Controller.js

function Controller($scope, SharedService){

 $scope.SharedService = SharedService;

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

// Uzyskaj dostęp do wartości w controllerertwo

ControllerTwo.js

function ControllerTwo($scope, SharedService){

 $scope.SharedService = SharedService;

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

Mam nadzieję że to pomoże.

DILIP KOSURI
źródło