it-swarm.com.ru

Как я могу поделиться данными $ scope между состояниями в angularjs ui-router?

Без использования службы или создания наблюдателей в родительском контроллере, как можно дать дочерним состояниям доступ к главному контроллеру $scope.

  .state("main", {
      controller:'mainController',
      url:"/main",
      templateUrl: "main_init.html"
  })  
  .state("main.1", {
      controller:'mainController',
      parent: 'main',
      url:"/1",
      templateUrl: 'form_1.html'
  })  
  .state("main.2", {
      controller:'mainController',
      parent: 'main',
      url: "/2",
      templateUrl: 'form_2.html'
  })  

Я не могу получить доступ к области mainController в дочернем состоянии - или, скорее, я получаю другой экземпляр этой области - не то, что я хочу. Я чувствую, что упускаю что-то простое. В объекте состояния есть опция конфигурации общих данных, но я не уверен, следует ли ее использовать для чего-то подобного.

71
sjt003

Я создал рабочий плункер , показывающий, как использовать $scope и UI-Router.

Определение состояния не изменилось:

$stateProvider
    // States
 .state("main", {
      controller:'mainController',
      url:"/main",
      templateUrl: "main_init.html"
  })  
  .state("main.1", {
      controller:'mainController',
      parent: 'main',
      url:"/1",
      templateUrl: 'form_1.html'
  })  
  .state("main.2", {
      controller:'mainController',
      parent: 'main',
      url: "/2",
      templateUrl: 'form_2.html'
  })  

Но у каждого государства может быть свой контроллер. Зачем? потому что каждое viewкаждого состояния получает new экземпляр определенного controllername__. Таким образом, хотя у нас есть mainControllername__, как показано ниже, мы можем быть уверены, что если мы перейдем к состоянию 'main.2', он будет создан дважды.

controller('mainController', function ($scope) {
  $scope.Model = $scope.Model || {Name : "xxx"};
})

Но что мы можем увидеть здесь , так это то, что мы проверяем, существует ли уже $scope.Model ... и если нет (родительское состояние) , мы создаем его с помощью новый intance {Name : "xxx"}.

Хорошо, что я говорю: только родительское состояние будет инициализировать $scope.Model. Все остальные получат это уже заполненным. Как? Ну вот ответ:

Наследование области действия только для иерархии представлений

Имейте в виду, что свойства области видимости наследуют цепочку состояний, только если представления ваших состояний вложены. Наследование свойств области не имеет ничего общего с вложенностью ваших состояний и имеет отношение к вложению ваших представлений (шаблонов).

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

Итак, как указано в документации. Поскольку наши дочерние представления вложены в родительское представление, область действия наследуется.

Понимание Области

В AngularJS дочерняя область обычно прототипно наследуется от своей родительской области.
...

Иметь '.' в ваших моделях будет обеспечено, что наследование прототипа находится в игре.

// So, use
<input type="text" ng-model="someObj.prop1"> 
// rather than
<input type="text" ng-model="prop1">.

И это все. Мы получаем наследование от UI-Router представлений и angular областей, и потому что мы умно использовали ссылочный тип (ModelNAME _), то есть имеем '.' точка в определении ng-model - теперь мы можем делиться данными

ПРИМЕЧАНИЕ: точка '.' в ng-model="Model.PropertyName просто означает, что существует referenceNAME _ объект Model {} с некоторым свойством: PropertyNamename __

Проверьте рабочий пример здесь

107
Radim Köhler

Вы можете получить всю область действия через $ rootScope . Если вам нужна только часть области действия, в ui-router есть функция пользовательские данные .

Вот как сделать многошаговую форму. Мне нужно, чтобы маршруты содержали информацию об их шагах в потоке.

Во-первых, у меня есть несколько маршрутов с UI-роутером:

  // Sign UP routes
  .state('sign-up', {
    abstract: true,
    url: '/sign-up',
    controller: 'SignupController',
    templateUrl: 'sign-up/index.html',
  })
  .state('sign-up.start', {
    url: '-start',
    templateUrl: 'sign-up/sign-up.start.html',
    data: { step: 0, title: 'Welcome to Mars!', },
  })
  .state('sign-up.expertise', {
    url: '-expertise',
    templateUrl: 'sign-up/sign-up.expertise.html',
    data: { step: 1, title: 'Your Expertise'},
  })

Обратите внимание:

  • элемент data в каждом маршруте.
  • Состояние abstract имеет SignupController. Это единственный контроллер для этой многошаговой формы. abstract не требуется, но имеет смысл для этого варианта использования.

SignupController.js

angular.module('app').controller('SignupController', function($scope, $state) {
  $scope.state = $state;
});

Здесь мы получаем $state ui-роутера и помещаем его в $scope

Вот основной шаблон 'sign-up/index.html':

<h2>{{state.current.data.title}}</h2>

<div>This is a multi-step-progress control {{state.current.data.step}}</div>

<form id="signUpForm" name="signUpForm" novalidate>
  <div ui-view></div>
</form>

Дочерние шаблоны могут быть любыми.

15
Michael Cole

Идея состоит в том, что вы используете область видимости в родительском наследовании:

 .state("main", {
      controller:'mainController',
      abstract: true,
      url:"/main",
      templateUrl: "main_init.html"
  })  
  .state("main.1", {
      controller:'mainController1',
      parent: 'main',
      url:"/1",
      templateUrl: 'form_1.html'
  })  
  .state("main.2", {
      controller:'mainController2',
      parent: 'main',
      url: "/2",
      templateUrl: 'form_2.html'
  })  

Чем использование простое, у вас есть 3 контроллера, один общий (mainController), и у каждого представления есть свой собственный.

9
Ben Diamant

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

.state("main", {
            url: "/main",
            templateUrl: "templates/Ders",
            controller: "DersController as DersC"
       }).state("main.child1", {
            url: "/child1",
            templateUrl: "templates/Ders/child1"
       }).state("main.child2", {
            url: "/child2",
            templateUrl: "templates/Ders/child2"
        })
7
Bahtiyar Özdere

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

1
hugsbrugs