2013-03-13 10 views
11

Devo creare una procedura guidata con più passaggi. Ogni fase mostrerà un modulo con le opzioni e, in base alle scelte dell'utente, la procedura guidata dovrebbe passare a un determinato passaggio, oltre a mantenere le preferenze dell'utente (scelte) memorizzate in qualche posto.Ember.js - Creazione di una procedura guidata multistep - Come?

Queste preferenze non vengono salvate nel modello, sono rilevanti solo per la fase di creazione del modello.

Al fine di dare un po 'di contesto, l'obiettivo di questo è:

  • rendere l'utente alcune domande per quanto riguarda le ore della sua attività di apertura. Ad esempio: È aperto nei fine settimana?, È diverso in estate?.
  • In base alle risposte a queste domande, verrà visualizzato un modulo finale per creare il/i modello/i degli orari.

La domanda è, quale sarebbe il modo migliore per realizzare questo all'interno di Ember?

qui sono i miei pensieri -Ember newbie-:

  • creare un modello per ogni passaggio della procedura guidata.
  • Tieni traccia del passaggio corrente. Dove? Controllore? Itinerario?
  • Visualizzare questi modelli in outlets, che deve essere reso dinamicamente in base al passaggio corrente. È qui che mi sento completamente perso. Come fare questo? Ogni passo dovrebbe avere un percorso diverso o no?
  • Tieni traccia delle risposte dell'utente nel controller .
  • Una volta completata la procedura guidata, caricare il modello di modulo, che leggerà le preferenze dell'utente memorizzate nel controller.

Versioni utilizzati:

  • Ember.VERSION: application.js 1.0.0-rc.1: 9268
  • Handlebars.VERSION: applicazione 1.0.0-rc.3 js: 9268
  • jQuery.VERSION: 1.9.1
+0

Sembra che tu abbia già qualche idea. Perché non provare a implementarli prima? Credo che le persone siano più propense ad aiutarti quando hai dimostrato uno sforzo per risolvere il tuo problema. – DaMainBoss

+0

http://stackoverflow.com/questions/14701856/ember-js-wizard-control <= Questo potrebbe essere d'aiuto;) Puoi avviare qualcosa in JSBin. – DaMainBoss

+0

@DaMainBoss in realtà ho provato per un paio d'ore e continuo a provare anche in questo momento. Iniziato con 'connectOutlet' dal controller e ha detto che i controller non hanno il metodo' connectOutlet', quindi lo hanno spostato alla vista, quindi provato con route. A un certo punto, tutti gli intenti sono falliti, ecco perché sto chiedendo delle linee guida sull'architettura e non esempi di codice reali, perché sento che sto pugnalando al buio. Inoltre, ho già visto quella domanda collegata, ma non è correlata alla mia domanda come sembra all'inizio. –

risposta

12

suona come siete sulla strada giusta.

Creare un modello per ogni passaggio della procedura guidata.

Sì, è un buon inizio.

Tieni traccia del passaggio corrente. Dove? Controllore? Itinerario?

O controller o percorso funzionerebbe.La rotta ha più senso se si desidera che gli URL bookmarkable per ogni passaggio e per back/forward funzionino ed è probabilmente la soluzione più semplice. Supporrà che tu abbia scelto la rotta.

Visualizzare questi modelli in punti vendita, che devono essere resi dinamicamente in base al passaggio corrente. Questo è dove mi sono completamente perso. Come fare questo? Ogni passo dovrebbe avere un percorso diverso o no?

Poiché ogni passaggio sarà un percorso, Ember si prenderà cura di rendere il modello appropriato automaticamente.

Tenere traccia delle risposte dell'utente nel controller.

Una volta completata la procedura guidata, caricare il modello di modulo, che leggerà le preferenze utente memorizzate nel controller.

Pensa a "finito" come solo un altro passaggio. Ogni fase ottiene il proprio controller che viene utilizzato per registrare le risposte degli utenti. L'ultimo controller utilizza "needs" per accedere ai controller precedenti al fine di personalizzare il comportamento in base alle risposte alla procedura guidata.

+1

ma quando si desidera salvare i dati prima di passare al passaggio successivo, come monitorare? – Nininea

2

Rispondere a una vecchia domanda nel caso in cui qualcuno abbia bisogno di risposte.

si può usare qualcosa di simile Multi-step form (or multiple "pages") in one route using Ember.js

questo utilizza 1 percorso e ogni passo/pagina è indicata o nascosto utilizzando {{# if}} Per rispondere alla domanda di Nino, quando ho realizzato questo ho avuto un oggetto nel mio controller tenere traccia di tutti i valori dei campi del modulo e aggiornarlo mentre clicco su Avanti. Quando si arriva all'ultima pagina in cui si invia, si può semplicemente collegare questo oggetto in funzione di presentare del vostro controller come questo

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 
} 

Per semplice implementazione di un modulo multi-pagina. Problema che ho con questo è che ho il codice dell'interfaccia utente jQuery che si aggancia alla didInsertElement della vista e funziona solo che quando passo da un passaggio all'altro e tornare (ogni pagina ha i pulsanti 'next' e 'prev'), trovo che qualunque sia il codice che è stato eseguito suInsertElement è stato annullato. È come se il pezzo di codice html non fosse solo nascosto e ri-mostrato. È stato ricaricato e quindi tutti gli effetti sono spariti.

8

So che questo thread vecchio e probabilmente non aiuterà l'OP, ma StackOverflow porta a più risposte di ogni altra cosa. Ho appena scritto un blog post su questo.

Guarda questo JSBin per vedere cosa ho fatto. Riassumo qui.

percorso a passo template:

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

proprietà calcolato personalizzata che cambia valori quando le rotte cambiano (in questo caso, quando i gradini delle modifiche Wizard)

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

Un oggetto route-value:

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

Un controller mixin per essere a conoscenza del cur affitto Route:

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

}); 

Il regolatore delle risorse:

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

Pensate dell'oggetto valore di percorso nel senso, "Quando il percorso è uguale a routeVal.route, le seguenti proprietà avranno questi valori" per esempio "Quando il percorso attualmente attivo è 'wizard.index' la prossima transizione è 'wizard.review', il testo del pulsante successivo è 'Review', il pulsante precedente deve essere nascosto, ecc. "

E infine il modello di risorsa:

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

Si può guardare a jsbin per quale sia il componente form-wizard (solo un involucro attorno al css per i wizard di Fuelux che mantiene la classe attiva sul passo corretto in base alla rotta). Il corpo della procedura guidata è il modello per ciascuno dei subroutes. Il testo del pulsante next/prev cambia a seconda del percorso, così come le loro transizioni (poiché la transizione dipende dallo stato corrente della procedura guidata). È più o meno un FSM

+1

+1 Molto utile! Tra il post sul blog di riferimento e il JS Bin, sono stato in grado di collegarlo insieme in un progetto CLI. La parte difficile era incorporare una "Proprietà del computer personalizzato". È scritto come dovrebbe essere importato, ma ho appena preso la funzione raw e l'ho rilasciata appena sopra la definizione del mio controller. Grazie molto! – Jim

+0

Bene, io uso quella funzione in molti punti, quindi l'uso di una classe util ho chiamato 'macros.js' per le proprietà calcolate. La sintassi per l'importazione di una funzione è leggermente diversa, quindi aggiornerò la risposta. Tu usi '{nome_fn}' – sunrize920

Problemi correlati