i-routerのFAQ には、bootstrap $ modalsとの統合に関するセクションがありますが、抽象ビューについては何も言及されていません。1つのビューの下に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コンテナーは空でした。
これを回避するための他のハッキーな方法をいくつか考えることができますが、これを処理する標準的な方法があるかどうかを確認するように依頼したいと思いました。
別の方法は、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>
実例のあるプランカーは次のとおりです。 http://plnkr.co/edit/Og2U2fZSc3VECtPdnhS1?p=preview
それが誰かを助けることを願っています!!
次のアプローチを使用してウィザードを開発しました。これはあなたの助けになるかもしれません。
以下のサンプルのような状態を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);
私は同じことに遭遇していました。私のために働いたのは、最初のサブ状態の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プロパティを指定する必要はありません。
私は同様のシナリオを扱いました。そこでは、ウィザードを作成する必要がありました(これにより、手順を実行し、最後に要約を押して保存することができます)。このために、私はさまざまなビューを作成しましたが、1つのコントローラーを使用しました。コントローラースコープは再ルーティングのたびに終了するため、コントローラーのスコープ(基本的にはウィザードに関連付けられたモデルオブジェクト)をウィザードのルーティングごとにサービスオブジェクトに保存し(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:
}
サービスまたはファクトリは、ユーザーセッションの存続期間を通じて維持され、ユーザーデータを保持するのに理想的です。役に立ったもう1つのことは、ルートでの「解決」の使用でした。必要なデータ(通常はルックアップデータ)がロードされなくなるまで、次のページがレンダリングされないようにします。解決のコードは次のようなものです。
.when('/RouteForWizardPage1', {
templateUrl: '/templates/ViewPage1Wizard.html',
caseInsensitiveMatch: true,
controller: 'wizardController',
resolve: {
wizardLookupDataPage1: function (Service) {
return service.getwizardModelLookupDataPage1().$promise;
}
},
})
マルチステップウィザードを作成するには、次のモジュールを使用できます(私は作成者です): https://github.com/troch/angular-multi-step-form 。
ビューのようなステップを作成でき、ナビゲーションを有効にできます(戻る/進むボタン、URL検索パラメーターを使用したURL)。例が利用可能です ここ 。
モーダルダイアログにウィザードを表示し、ウィザードのステップごとに個別の状態を設定する場合は、モーダルダイアログが完全にビュー階層の外側にレンダリングされることに注意する必要があります。したがって、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
状態定義と同様の形式を使用)、ウィザードを進めるためのメソッドを提供し、適切なビューをレンダリングすることができました。ダイアログ内の/ controller。
次のステップに進むたびにモーダルを起動するかどうかはわかりません。
モーダルビュー()を作成するだけで、各ステップにモーダル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">×</button>
<h4 class="modal-title">Modal title</h4>
</div>
<div class="modal-body">
<p>One fine body…</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 = "modal"を追加すると、完了です。