[Angularjs] 使用带引导程序$ modal的angular-ui-router创建一个多步向导



Answers

我用下面的方法来开发一个向导。 这可能对你有帮助。

我使用下面的样本与属性状态。

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

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容器是空的。

我可以想一些其他的hacky方法来解决这个问题,但是我想问一下看看是否有一个经典的方法来处理这个问题。




如果要在模态对话框中显示向导,并且每个向导的步骤都有单独的状态,则需要记住模式对话框完全呈现在视图层次结构之外。 因此,你不能指望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状态定义的格式),提供向前移动向导的方法,以及在对话框中呈现合适的视图/控制器。




我已经处理了类似的情况,我必须创建一个向导(它可以让你通过步骤,最后点击汇总和保存)。 为此,我创建了不同的视图,但只有一个控制器。 由于控制器作用域在每次重新路由后都会死亡,因此我必须将控制器(基本上与向导关联的模型对象)的作用域保存在向导中的每个路由的服务对象中(通过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:
}

服务或工厂在用户会话的整个生命周期内都是持久的,并且是保存用户数据的理想选择。 还有一件有用的东西是在路线中使用“解决”。 它确保下一个页面不会被渲染,直到所需的数据(通常是查找数据)未被加载。 代码解析是这样的:

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



Links