2013-03-13 8 views
11

複数のステップでウィザードを作成する必要があります。各ステップにはオプションのあるフォームが表示され、ユーザーの選択に応じて、ウィザードは特定の手順に進み、ユーザーの設定(選択肢)をある場所に保存します。Ember.js - 多段階ウィザードを作成する方法?

これらの設定はモデルに保存されず、モデル作成のステップにのみ関連します。

いくつかのコンテキストを与えるために、これの目標は次のとおりです。

  • ユーザー彼のビジネスの営業時間に関するいくつかの質問を行います。例:週末は営業していますか?夏は違いますか?
  • これらの質問の答えに応じて、最終的なフォームが表示され、タイムテーブルモデルが作成されます。

Emberの内部でこれを達成するにはどうすればよいでしょうか?ここで

は私-Ember newbie-の考えです:

  • 各ウィザードステップのためのテンプレートを作成します。
  • 現在の手順を追跡します。 どこ?コントローラ?ルート?
  • これらのテンプレートをoutletsに表示します。このテンプレートは、現在の手順に従って動的に表示する必要があります。 これは私が完全に失われたところです。これを行う方法?それぞれのステップに異なるルートを設定する必要がありますか?
  • コントローラでユーザーの回答を追跡します。
  • ウィザードが完了したら、フォームテンプレートを読み込み、コントローラに保存されているユーザー設定を読み込みます。使用されている

バージョン:

  • Ember.VERSION:1.0.0-rc.1のapplication.js:9268
  • Handlebars.VERSION:1.0.0-rc.3アプリケーション.js:9268
  • jQuery.VERSION:1.9.1
+0

あなたはすでにいくつかのアイデアを持っているようです。最初に実装しようとしないのはなぜですか?私はあなたの問題を解決する努力を示してくれたとき、人々はあなたを助ける可能性が高いと思う。 – DaMainBoss

+0

http://stackoverflow.com/questions/14701856/ember-js-wizard-control <=これは助けになるかもしれません;)JSBinで何かを始めることができます。 – DaMainBoss

+0

@DaMainBoss実際に私は数時間努力していて、まだこの瞬間も試しています。コントローラーから 'connectOutlet'で始まり、コントローラーには' connectOutlet'メソッドがなく、それをビューに移動してからルートで試してみたと言いました。ある時点ですべての意図が失われてしまったので、実際のコード例ではなくアーキテクチャーのガイドラインを求めています。なぜなら私は暗闇の中で刺すように感じているからです。また、既にそのリンクされた質問を見たが、それは私の質問に最初に似ているように関連していない。 –

答えて

12

あなたは正しい軌道に乗っているような音。

ウィザードステップごとにテンプレートを作成します。

はい、これは良いスタートです。

現在の手順を記録します。どこ?コントローラ?ルート?

いずれのコントローラまたはルートも機能します。各ステップごとにブックマーク可能なURLを使用し、前後/後ろを機能させる場合は、ルートが最も効果的です。これはおそらく最も単純な解決策です。あなたがルートを選択したと仮定します。

これらのテンプレートをアウトレットに表示します。アウトレットは、現在の手順に従って動的に表示する必要があります。これは私が完全に失われたところです。これを行う方法?それぞれのステップに異なるルートを設定する必要がありますか?

各ステップがルートになるので、emberは適切なテンプレートを自動的にレンダリングすることに注意します。

コントローラーでのユーザーの応答を記録します。

ウィザードが完了したら、フォームテンプレートを読み込み、コントローラに保存されているユーザー設定を読み込みます。

もう1つのステップとして「完了」と考えてください。各ステップは、ユーザーの応答を記録するために使用される独自のコントローラーを取得します。最後のコントローラは、ウィザードへの応答に基づいて動作をカスタマイズするために、「ニーズ」を使用して以前のコントローラにアクセスします。

+1

しかし、次のステップに進む前にデータを保存したいときは、どのように追跡できますか? – Nininea

2

誰かが何らかの回答が必要な場合に備えて、古い質問に回答してください。

あなたは私がこれを実装したときに、私は、オブジェクトを持っていた、ニノの質問に答えるために これは1つのルートを利用して、各ステップ/ページは{{#ifのを}}を使用して表示または非表示になっている。この Multi-step form (or multiple "pages") in one route using Ember.js

のようなものを使用することができます私のコントローラでは、フォームフィールドのすべての値を把握し、次にクリックすると更新されます。あなたが提出最後のページに到達すると、単にあなたのコントローラの複数ページのフォームの簡単な実装のための良いこの

submitSurvey: function() { 
    var survey = this.store.createRecord('survey', this.get('surveyObj')); 
    // surveyObj contains all the form field's values that you've been 
    // keeping track of everytime you go from one step to another 
    survey.save(); 
    this.transitionToRoute('somewhere'); // go somewhere after submitting the form 
    this.set('firstPage', true); // make first page the page to show 
    this.set('lastPage', false); 
    this.init(); 
    // constructor's init contains code that empties all the form fields alternatively 
    // you can create a separate function instead of using init 
} 

のような機能を提出するには、このオブジェクトを接続することができます。問題これは、ビューのdidInsertElementにフックするjQuery UIコードがあり、あるステップから別のステップに移動して戻ってきたとき(各ページに '次へ'と '前'ボタンがある場合)に動作します。 didInsertElementで実行されたコードが元に戻されます。 HTMLコードのチャンクが隠されて再表示されたようなものではありません。それは再ロードされ、したがってすべての影響はなくなった。

8

私はこの古いスレッドを知っていて、おそらくOPを助けませんが、stackoverflowは何よりも多くの答えにつながります。私はちょうどこれにblog postを書きました。

このJSBinを見て、私が行ったことを見てください。私はここで要約します。

テンプレートのステップ当たりルート:

Router.map(function() { 
    this.resource('wizard', function(){ 
    this.route('index'); 
    this.route('review'); 
    this.route('complete'); 
    }); 
}); 

ルート変更(ここでは、ウィザードの変更ステップ)

import Ember from 'ember'; 
var get = Ember.get; 
var computed = Ember.computed; 

export function routeVal(routeVals, prop){ 
    return computed('currentPath', function(){ 
     var currentRoute = get(this, 'currentPath'); 
     var routeValues = get(this, routeVals); 
     for (var i = 0; i < routeValues.length; i++) { 
      if (routeValues[i].route === currentRoute) { 
       return routeValues[i][prop]; 
      } 
     } 
    }); 
} 

route-valueオブジェクトの値を変更するカスタム計算プロパティ:

export default Ember.Object.extend({ 
    route: null 
    //all other props can be added dynamically 
}); 

カーソルを認識するためのコントローラミックスイン家賃ルート:

export default Ember.Mixin.create({ 
    needs: ['application'], 
    currentPath: Ember.computed.alias("controllers.application.currentPath") 

}); 

リソースコントローラ:

import CurrentRouteAware from 'path/to/mixin'; 
import {routeVal} from 'app_name/utils/macros'; 
export default Ember.Controller.extend(CurrentRouteAware, { 
    routeValues: [ 
     RouteVal.create({ 
      route: 'wizard.index', 
      step: 'Create', 
      next: 'Review', 
      nextTransition: 'wizard.review', 
      prevTransition: 'wizard.index', 
      showNext: true, 
      showPrev: false 
     }), 
     RouteVal.create({ 
      route: 'wizard.review', 
      step: 'Review', 
      next: 'Complete', 
      prev: 'Create', 
      nextTransition: 'wizard.complete', 
      prevTransition: 'wizard.index', 
      showNext: true, 
      showPrev: true 
     }), 
     RouteVal.create({ 
      route: 'wizard.complete', 
      step: 'Complete', 
      next: 'Make Another', 
      prev: 'Review', 
      nextTransition: 'wizard.complete', 
      prevTransition: 'wizard.review', 
      showNext: false, 
      showPrev: true 
     }) 
    ], 
    nextButton: routeVal('routeValues', 'next'), 
    prevButton: routeVal('routeValues', 'prev'), 
    nextTransition: routeVal('routeValues', 'nextTransition'), 
    showButtons: routeVal('routeValues', 'showButtons'), 
    prevTransition: routeVal('routeValues', 'prevTransition'), 
    showNext: routeVal('routeValues', 'showNext'), 
    showPrev: routeVal('routeValues', 'showPrev'), 
    actions: { 
     next: function(){ 
      this.transitionToRoute(this.get('nextTransition')); 
     }, 
     prev: function(){ 
      this.transitionToRoute(this.get('prevTransition')); 
     } 
    } 
}); 

意味としてルート値オブジェクトを考える、「ルートはrouteVal.routeに等しい場合、次のプロパティがありますこれらの値」、例えば「現在アクティブなルートは 'wizard.index'、次のトランジションは 'wizard.review'、次のボタンテキストは 'Review'、前のボタンは非表示にするなど。

最後に、

<div class="wizard" id="wizardIllustration"> 
    {{form-wizard steps=routeValues currentPath=currentPath}} 
    <div class="actions"> 
    {{#if showPrev}} 
    <button type="button" {{action 'prev'}}class="btn btn-default btn-prev"><span class="glyphicon glyphicon-arrow-left"></span>{{prevButton}}</button> 
    {{/if}} 
    {{#if showNext}} 
    <button {{action 'next'}}type="button" class="btn btn-default btn-next" >{{nextButton}}<span class="glyphicon glyphicon-arrow-right"></span></button> 
    {{/if}} 
    </div> 
    <div class="step-content"> 
    {{outlet}} 
    </div> 

</div> 

フォームウィザードコンポーネントの内容を確認することができます(ルートに基づいて正しいステップにアクティブクラスを保持するFueluxウィザードのcssをラップするだけです)。ウィザードの本文は、各サブルートのテンプレートです。 next/prevボタンのテキストは、トランジションと同様にルートに応じて変わります(トランジションはウィザードの現在の状態に依存するため)。それは多かれ少なかれFSMです

+1

+1非常に便利です!参照されたブログ投稿とJS Binの間で、私はCLIプロジェクトでこれを一緒に綴ることができました。そのトリッキーな部分は、「カスタムコンピュータプロパティ」を組み込んでいました。それはインポートする必要があるように書かれていますが、私は生の関数を取り出してコントローラ定義の上にドロップしました。どうもありがとう! – Jim

+0

私は多くの場所でその関数を使用しています。したがって、計算されたプロパティに 'マクロス.js'と呼ばれるutilクラスを使用しています。関数をインポートするための構文は少し異なりますので、その答えを更新します。 '{fn_name}'を使うと – sunrize920

関連する問題