Angularjs, передача области между маршрутами

87

У меня ситуация с формой, которая растягивается на несколько страниц (может быть, не идеальна, но так оно и есть). Я хотел бы иметь одну область видимости для всей формы, которая заполняется по мере продвижения, чтобы, если пользователь переходит между шагами, легко запомнить состояние.

Так что мне нужно сделать очень псевдокодом:

  1. Задавать $scope.val = <Some dynamic data>
  2. Щелкните ссылку, чтобы перейти к новому шаблону (возможно, с тем же контроллером).
  3. $scope.val все равно должно быть то же значение, что и на последней странице.

Является ли сохранение данных для области правильным способом решения этой проблемы или есть другой способ? Можете ли вы даже создать контроллер, который имеет постоянную область видимости между маршрутами, за исключением, конечно, сохранения его в базе данных.

Эрик Хонн
источник
Просто как дополнение к ganaraj: здесь вы найдете действительно интересную запись в блоге со скринкастом о том, как заставить различные контроллеры взаимодействовать. Также есть несколько полезных jsfiddles, с которыми можно поиграть. onehungrymind.com/angularjs-communicating-between-controllers Я надеюсь, что это поможет.
F Lekschas

Ответы:

138

Вам необходимо использовать службу, поскольку она будет существовать на протяжении всего жизненного цикла вашего приложения.

Допустим, вы хотите сохранить данные, относящиеся к пользователю.

Вот как вы определяете услугу:

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

В вашем первом контроллере:

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

    });
Ганарадж
источник
6
Аааа! Я пробовал это раньше, но не смог заставить его работать, потому что я использовал один и тот же контроллер для обоих маршрутов, поэтому на каждом новом маршруте значения по умолчанию будут перезаписывать те, которые я ввел на предыдущей странице. С двумя контроллерами или без значений по умолчанию этого больше не происходит. Благодарность!
Эрик Хонн,
1
Что насчет Value Recipe docs.angularjs.org/guide/providers , например myApp.value('clientId', 'a12345654321x');, сохраняется ли он между маршрутами?
The Bndr
@TheBndr: Так и должно быть. Ценности - это просто особая форма услуг, как я понимаю.
Роберт Коритник
3
Службы не сохранят данные, если вы перезагрузите страницу ... Поэтому, если вы находитесь на странице 4 своей формы и перезагружаете эту страницу, вы потеряете все заполненные данные.
danielrvt 08
1
Хороший ответ! В качестве дополнительного момента, руководство по стилю для тех, кто принимает этот ответ - службы, которые сами не являются конструкторами (т.е. используются как новый XX), следует называть строчными верблюдами: github.com/mgechev/angularjs-style-guide .
Мэтт Бирн
9

Сервис будет работать, но логичный способ сделать это с использованием только обычных областей видимости и контроллеров - настроить контроллеры и элементы таким образом, чтобы они отражали структуру вашей модели. В частности, вам нужны родительский элемент и контроллер, которые устанавливают родительскую область. Отдельные страницы формы должны находиться в представлении, которое является дочерним по отношению к родительскому. Родительская область сохраняется даже при обновлении дочернего представления.

Я предполагаю, что вы используете ui-router, чтобы иметь вложенные именованные представления. Затем в псевдокоде:

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

Затем WizardController определяет переменные области видимости, которые вы хотите сохранить на всех этапах многостраничной формы (которую я называю «мастером»). Тогда будут обновляться stepViewтолько ваши маршруты . Каждый шаг может иметь свои собственные шаблоны, контроллеры и области действия, но их области действия теряются от страницы к странице. Но области в WizardController сохраняются на всех страницах.

Чтобы обновить области WizardController из дочерних контроллеров, вам нужно будет использовать синтаксис, например, $scope.$parent.myProp = 'value'или определить функцию setMyPropв WizardController для каждой переменной области. В противном случае, если вы попытаетесь установить переменные родительской области видимости непосредственно из дочерних контроллеров, вы в конечном итоге просто создадите новую переменную области видимости для самого дочернего элемента, затеняя родительскую переменную.

Сложно объяснить, и я прошу прощения за отсутствие полного примера. По сути, вам нужен родительский контроллер, который устанавливает родительскую область, которая будет сохраняться на всех страницах вашей формы.

tksfz
источник
1
Да, это будет работать с ui-router (и это довольно хороший способ создать такую ​​страницу), но не из коробки. Метод обслуживания - это уже готовый продукт.
Erik Honn
1
Чтобы уточнить, свойства родительской области всегда будут унаследованы дочерней областью. Однако, если вы хотите установить свойство родительской области из дочерней области, вам необходимо получить к ней доступ в родительской области, иначе вы создаете новое свойство с тем же именем в дочерней области. Установить свойство родительской области можно следующим образом:$scope.$parent.myProp = 'hello world';
mbursill
1
Это намного приятнее, чем использование сервиса. Сервисы являются одиночными, поэтому любое определенное там состояние является глобальным для приложения. Если пользователь выйдет из мастера на полпути, а затем перезапустит его, в службе останется состояние, оставшееся от предыдущего запуска - если вы не убедитесь, что вы правильно очищаете службу в каждой точке выхода, но это может вполне легко становится серьезной головной болью при обслуживании!
Дэн Кинг
Намного более заинтересован в этом ответе
Kurai Bankusu
Сервисы - это первое, что приходит на ум, если вы не используете Angular UI Router. Однако, если вы используете UI Router, у него есть вложенные решения, которые могут сохранять информацию между вложенными представлениями. Я думаю, что это был бы более чистый подход, чем попытка получить доступ к родительской области. medium.com/opinionated-angularjs/...
losmescaleros
5

Данные могут передаваться между контроллерами двумя способами.

  1. $rootScope
  2. Модель

Пример ниже демонстрирует передачу значений с использованием модели

app.js

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

SharedService.js

function SharedService($rootScope){

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

// Изменяем значение в контроллере A

Controller.js

function Controller($scope, SharedService){

 $scope.SharedService = SharedService;

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

// Доступ к значению в контроллере два

ControllerTwo.js

function ControllerTwo($scope, SharedService){

 $scope.SharedService = SharedService;

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

Надеюсь это поможет.

ДИЛИП КОСУРИ
источник