使用angular-ui-router和bootstrap $ modal来创建一个多步向导

时间:2014-01-26 19:06:32

标签: angularjs twitter-bootstrap dialog modal-dialog angular-ui-router

FAQ for ui-router有一个关于与bootstrap $ modals集成的部分,但它没有提到有关抽象视图的任何内容。我在一个抽象视图下有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块添加到抽象状态,并从3个子状态中的每一个中删除onEnter。这在我看来似乎是正确的方法。抽象状态初始化并打开$ modal,后续状态应该插入,但是当我尝试这个时,ui-view容器是空的。

我可以想到其他一些黑客的方法来解决这个问题,但我想问一下,看看是否有规范的处理方法。

7 个答案:

答案 0 :(得分:4)

替代方法是在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

希望有人帮助!!

答案 1 :(得分:1)

我使用以下方法开发向导。这可能对你有帮助。

我使用属性下面的状态。

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

答案 2 :(得分:0)

我不确定你每次进行下一步都想要发射模态。

我认为您所要做的就是创建一个模态视图()然后每一步都有一个模态,分配给它的templateUrl。

每个模板应如下所示:


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

在最后一个屏幕上,你可以添加一个data-dismiss =&#34; modal&#34;提交,你完成了

答案 3 :(得分:0)

我已经处理过类似的场景,我必须创建一个向导(允许你完成步骤,最后点击摘要并保存)。 为此,我创建了不同的视图但只有一个控制器。 由于控制器范围在每次重新路由后死亡,我不得不在控制器(通过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:
}

服务或工厂在用户会话的整个生命周期内保持不变,是保存用户数据的理想选择。 另一件有用的事情是在路线中使用'Resolve'。 它确保在未加载所需数据(通常是查找数据)之前不会呈现下一页。解决方案是这样的:

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

答案 4 :(得分:0)

我遇到了同样的事情..对我有用的是清空第一个子状态的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属性。

答案 5 :(得分:0)

如果要在模式对话框中显示向导并为每个向导的步骤设置单独的状态,则需要记住模式对话框完全呈现在视图层次结构之外。因此,您不能指望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状态定义的格式),提供推进向导的方法,并呈现适当的视图/对话框内的控制器。

答案 6 :(得分:0)

要创建多步向导,您可以使用此模块(我是作者):https://github.com/troch/angular-multi-step-form

它允许您创建视图等步骤,并且您可以启用导航(后退/前进按钮,带有URL搜索参数的URL)。示例可用here