utilisez angular-ui-router avec bootstrap $modal pour créer un assistant multi-étapes

FAQ pour ui-router a une section sur l'intégration avec bootstrap $modals, mais elle ne mentionne rien sur les vues abstraites. J'ai 3 vues sous une seule vue abstraite, donc quelque chose comme ce qui suit.

 $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'
      ...
    }); 
}]);

j'ai aussi essayé d'ajouter seulement le bloc onEnter à l'état abstrait, et de supprimer onEnter de chacun des 3 états enfants. Cela me semble être la bonne approche. L'état abstrait initialise et ouvre le $ modal et le les états suivants devraient interpoler dans, mais quand j'ai essayé ceci le conteneur ui-view était vide.

je peux penser à d'autres moyens détournés pour contourner cela, mais j'ai pensé que je demanderais pour voir s'il y a une façon canonique de gérer cela.

27
demandé sur Charles 2014-01-26 23:06:31

7 réponses

Alternative est d'utiliser ng-switchng-include combinaison à l'intérieur de $modal contrôleur de charger dynamiquement étape de l'assistant de modèles, c'est si vous n'avez pas l'esprit de partage le même contrôleur pour toutes les étapes de l'assistant:

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

Voici Plunker avec Exemple de travail:http://plnkr.co/edit/Og2U2fZSc3VECtPdnhS1?p=preview

j'Espère que l'aide à quelqu'un !!

4
répondu mik-t 2015-04-13 14:47:27

j'ai utilisé l'approche suivante pour développer un assistant. cela peut être de l'aide pour vous.

j'ai utilisé des États comme ci-dessous échantillon avec parent propriété.

 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);
1
répondu Seminda 2014-10-09 21:57:20

Je ne suis pas sûr que vous vouliez virer le modal à chaque fois que vous allez à l'étape suivante.

je pense que tout ce que vous avez à faire est de créer une vue modale () alors chaque étape a un modal a templateUrl assigné à elle.

chaque modèle doit ressembler à:


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

Sur le dernier écran vous pouvez ajouter un data-dismiss= "modal" à la soumission et vous êtes fait

0
répondu Bo Lora 2014-03-13 20:20:37

j'ai eu affaire à un scénario similaire, où j'ai dû créer un assistant (qui vous permet de passer par étapes et finalement cliquer sur résumé et enregistrer). Pour cela, j'avais créé des vues différentes mais avec un contrôleur. Puisque la portée du contrôleur meurt après chaque réacheminement, j'ai dû enregistrer la portée du contrôleur(essentiellement l'objet model associé à l'assistant) dans un objet de service pour chaque routage de l'Assistant (capturé par le biais de l'emplacement.chemin ()) et chargez cet objet en arrière de l'objet de service sur la charge de contrôleur.Quelque chose comme ci-dessous:-

// 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:
}

le Service ou l'usine est maintenu tout au long de la durée de vie de la session de l'utilisateur et est idéal pour tenir les données de l'utilisateur. Une autre chose qui a été utile, a été l'utilisation de la "résolution" dans les itinéraires. Il s'assure que la page suivante n'est pas rendue tant que les données requises(généralement les données de recherche) ne sont pas chargées. Le Code de resolve est quelque chose comme ceci:

.when('/RouteForWizardPage1', {
                templateUrl: '/templates/ViewPage1Wizard.html',
                caseInsensitiveMatch: true,
                controller: 'wizardController',
                resolve: {
                   wizardLookupDataPage1: function (Service) {
                        return service.getwizardModelLookupDataPage1().$promise;
                    }
                },
            })
0
répondu Pramod Sharma 2014-09-02 04:06:54

je suis tombé sur la même chose.. Ce qui a fonctionné pour moi était de vider la propriété url du premier sous-état. Par conséquent, pour le premier sous-État, votre code devrait ressembler à ce qui suit:

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

aussi, incase vous n'utilisez pas la propriété url pour appeler les 3 autres sous-états, et vous les appelez en utilisant le nom de l'état seulement, vous n'avez pas nécessairement besoin de mentionner une propriété url pour eux.

0
répondu Karan Kapoor 2014-11-21 19:34:45

si vous voulez afficher un assistant dans un Dialogue modal et avoir un État séparé pour chacune des étapes de l'assistant, vous devez garder à l'esprit que le Dialogue modal est rendu complètement en dehors de votre hiérarchie de vue. Par conséquent, vous ne pouvez pas vous attendre à une interaction entre

une solution robuste est de mettre la logique de manipulation du contenu de l'assistant sur la portée de l'état parent

$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,
            // ...
        });
    }
};

et ensuite afficher manuellement le le contenu approprié de chacun des sous-états et manipuler la portée de l'assistant au besoin

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

lorsque nous avons fait face à ce problème dans notre projet, nous avons décidé après discussion, que nous n'avions pas besoin de se séparer ui-router indique les étapes du magicien. Cela nous a permis de créer un wizard directive utilisée dans le modèle de dialogue pour lire la configuration de l'assistant à partir de scope (en utilisant un format similaire à ui-router définition de l'état), fournissent des méthodes pour faire progresser la assistant, et de rendre approprié de vue/contrôleur à l'intérieur de la boîte de dialogue.

0
répondu hon2a 2014-11-23 12:42:16

Pour créer des multi-étape de l'assistant, vous pouvez utiliser ce module (je suis l'auteur): https://github.com/troch/angular-multi-step-form.

il vous permet de créer des étapes comme des vues, et vous pouvez activer la navigation (bouton Retour / avant, url avec un paramètre de recherche URL). Des exemples sont disponibles ici.

0
répondu Thomas Roch 2015-06-19 15:10:16