Подтвердить что ты не робот

Используйте angular -ui-router с bootstrap $modal для создания многоэтапного мастера

FAQ для ui-router содержит раздел об интеграции с модальностями bootstrap $, но он ничего не говорит о абстрактных представлениях. У меня есть 3 представления под одним абстрактным видом, поэтому примерно следующее.

 $stateProvider
   .state('setup', {
     url: '/setup',
     templateUrl: 'initialSetup.html',
     controller: 'InitialSetupCtrl',
     'abstract': true
   })  

   // markup for the static view is
   <div class="wizard">
     <div ui-view></div>
   </div> 

   .state('setup.stepOne', {
      url: '/stepOne',
      controller: 'SetupStepOneCtrl',
      onEnter: function($stateParams, $state, $modal) {
        $modal.open{
          backdrop: 'static',
          templateUrl: 'setup.stepOne.html',
          controller: 'SetupStepOneCtrl'
        })
      }   
   })  

   .state('setup.stepTwo', {
     url: '/stepTwo',
     controller: 'SetupStepTwoCtrl',
     onEnter: function($stateParams, $state, $modal) {
       $modal.open({
         backdrop: 'static',
         templateUrl: 'setup.stepTwo.html',
         controller: 'SetupStepTwoCtrl'
       })
     }   
    })  

    .state('setup.stepThree', {
      url: '/stepThree',
      templateUrl: 'setup.stepThree.html',
      controller: 'SetupStepThreeCtrl'
      ...
    }); 
}]);

Я также попытался добавить блок onEnter в абстрактное состояние и удалить onEnter из каждого из трех дочерних состояний. На самом деле это кажется мне правильным. Абстрактное состояние инициализирует и открывает $modal, а последующие состояния должны интерполироваться, но когда я это пробовал, контейнер ui-view был пуст.

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

4b9b3361

Ответ 1

Альтернативный способ - использовать ng-switch с комбинацией ng-include внутри контроллера $modal для динамической загрузки шаблонов шага мастера, то есть если вы не против совместного использования одного и того же контроллера для всех шагов мастера:

<div ng-switch="currentStep.number">
  <div ng-switch-when="1">
    <ng-include src="'wizardModalStep1.html'"></ng-include>
  </div>
  <div ng-switch-when="2">
    <ng-include src="'wizardModalStep2.html'"></ng-include>
  </div>
  <div ng-switch-when="3">
    <ng-include src="'wizardModalStep3.html'"></ng-include>
  </div>
</div>

Вот Plunker с рабочим примером: http://plnkr.co/edit/Og2U2fZSc3VECtPdnhS1?p=preview

Надеюсь, что это поможет кому-то!

Ответ 2

Я использовал следующий подход для разработки мастера. это может помочь вам.

Я использовал состояния, подобные приведенному ниже, с свойством parent.

 var home = {
            name: 'home',
            url: '/home',
            controller: 'MainController',
            templateUrl: '/html/main.html'
        },
        sampleWizard = {
            name: 'sampleWizard',
            url: '/sampleWizard',
            controller: 'sampleWizardController',
            templateUrl: '/html/sd/sample/sampleWizard.html'
        },
         sampleSectionOne = {
             name: 'sampleSectionOne',
             url: '/sampleSectionOne',
             parent: sampleWizard,
            controller: 'sampleSectionOneController',
            templateUrl: '/html/sd/sample/sampleSectionOne.html'
        },
        sampleSectionTwo = {
            name: 'sampleSectionTwo',
            url: '/sampleSectionTwo',
            parent: sampleWizard,
            controller: 'sampleSectionTwoController',
            templateUrl: '/html/sd/sample/sampleSectionTwo.html'
        };

        $stateProvider.state(home);
        $stateProvider.state(sampleWizard);
        $stateProvider.state(sampleSectionOne);
        $stateProvider.state(sampleSectionTwo);

Ответ 3

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

Я думаю, что все, что вам нужно сделать, это создать модальный вид(), тогда на каждом шаге есть модальный шаблон, назначенный ему.

каждый шаблон должен выглядеть так:


<div class="modal fade in" id="whatever" style="display:block">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
                <h4 class="modal-title">Modal title</h4>
            </div>
            <div class="modal-body">
                <p>One fine body&hellip;</p>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
                <a ui-sref="next_page_route_id" type="button" class="btn btn-primary">Next</a>
            </div>
        </div><!-- /.modal-content -->
    </div><!-- /.modal-dialog -->
</div><!-- /.modal -->

<div class="modal-backdrop fade in"></div>

На последнем экране вы можете добавить submit-reject = "modal" в submit, и вы закончили

Ответ 4

Я имел дело с похожим сценарием, где мне приходилось создавать мастер (который позволяет вам пройти шаги и, наконец, нажать на сводку и сохранить). Для этого я создал разные представления, но с одним контроллером. Поскольку размер контроллера уменьшается после каждой повторной маршрутизации, мне пришлось сохранить область действия контроллера (в основном объект модели, связанного с мастером) в объекте службы для каждой маршрутизации в мастере (Captured through location.path()) и загрузить эту объект обратно из служебного объекта при загрузке контроллера. Что-то вроде ниже: -

// Saving data on routing
 $scope.nextPage = function () {
        service.ModelForWizard = $scope.ModelForWizard;
        switch ($location.path()) {
        case RouteOfPage1:
            //Do some stuff
            break;
        case RouteOfPage2:
           //Do some stuff
            break;

        default:
}

Сервис или factory сохраняется на протяжении всего срока службы пользовательского сеанса и идеально подходит для хранения пользовательских данных. Еще одна полезная вещь - использование "Разрешить" на маршрутах. Это гарантирует, что следующая страница не отображается, пока требуемые данные (обычно данные поиска) не будут загружены. Код разрешения - это примерно так:

.when('/RouteForWizardPage1', {
                templateUrl: '/templates/ViewPage1Wizard.html',
                caseInsensitiveMatch: true,
                controller: 'wizardController',
                resolve: {
                   wizardLookupDataPage1: function (Service) {
                        return service.getwizardModelLookupDataPage1().$promise;
                    }
                },
            })

Ответ 5

Я работал в одном и том же. Что сработало для меня, это опорожнение свойства url первого под-состояния. Следовательно, для первого дополнительного состояния ваш код должен выглядеть следующим образом:

    .state('setup.stepOne', {
      url: '',
      controller: 'SetupStepOneCtrl',
      onEnter: function($stateParams, $state, $modal) {
        $modal.open{
          backdrop: 'static',
          templateUrl: 'setup.stepOne.html',
          controller: 'SetupStepOneCtrl'
        })
      }   
   })  

Кроме того, если вы не используете свойство url для вызова других 3-х под-состояний и вызываете их только с использованием имени состояния, вам необязательно упоминать свойство URL-адреса для них.

Ответ 6

Если вы хотите показать мастер в модальном диалоговом окне и иметь отдельное состояние для каждого из шагов мастера, вам нужно иметь в виду, что модальный диалог отображается полностью вне вашей иерархии представлений. Поэтому вы не можете ожидать какого-либо взаимодействия между механизмами рендеринга ui-router и содержимым диалогового окна.

Надежное решение состоит в том, чтобы поместить логику управления содержимым мастера в область родительского состояния

$scope.wizard = {
    scope: $scope.$new(),
    show: function (template) {
        // open the $modal if not open yet
        // purge scope using angular.copy()
        // return $scope.wizard.scope
    },
    // private
    open: function () {
        $modal.open({
            scope: $scope.wizard.scope,
            // ...
        });
    }
};

а затем вручную отобразить соответствующий контент из каждого из под-состояний и при необходимости манипулировать областью мастера

$scope.wizard.show('someTemplate');
$scope.wizard.scope.user = ...;

Когда мы столкнулись с этой проблемой в нашем проекте, мы решили после некоторого обсуждения, что нам действительно не нужны отдельные состояния ui-router для шагов мастера. Это позволило нам создать директиву wizard, используемую внутри шаблона диалога, чтобы прочитать конфигурацию мастера из области действия (используя формат, аналогичный определению состояния ui-router), предоставить методы для продвижения мастера и визуализировать соответствующий вид/контроллер внутри диалогового окна.

Ответ 7

Чтобы создать многошаговые мастера, вы можете использовать этот модуль (я автор): https://github.com/troch/angular-multi-step-form.

Он позволяет создавать шаги, подобные представлениям, и вы можете включить навигацию (кнопка назад/вперед, URL-адрес с параметром поиска URL). Примеры здесь.