I need to create a wizard with multiple steps. Each step will display a form with options, and depending on the user choices, the wizard should go to a certain step, as well as
I know this an old thread and probably won't help the OP, but stackoverflow leads to more answers than anything else. I just wrote a blog post on this.
Look at this JSBin to see what I've done. I'll summarize here.
Route per step in template:
Router.map(function() {
this.resource('wizard', function(){
this.route('index');
this.route('review');
this.route('complete');
});
});
Custom computed property that changes values when the routes change (in this case when the steps of the wizard changes)
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];
}
}
});
}
A route-value
object:
export default Ember.Object.extend({
route: null
//all other props can be added dynamically
});
A controller mixin for being aware of the current route:
export default Ember.Mixin.create({
needs: ['application'],
currentPath: Ember.computed.alias("controllers.application.currentPath")
});
The resource controller:
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'));
}
}
});
Think of the route value object as meaning, "When the route equals routeVal.route, the following properties will have these values" eg "When the currently active route is 'wizard.index' the next transition is to 'wizard.review', the next button text is 'Review', the previous button should be hidden, etc"
And lastly, your resource template:
{{form-wizard steps=routeValues currentPath=currentPath}}
{{#if showPrev}}
{{/if}}
{{#if showNext}}
{{/if}}
{{outlet}}
You can look at the jsbin for what the form-wizard component was (just a wrapping around the css for Fuelux wizards that keeps the active class on the correct step based on the route). The body of the wizard is the template for each of the subroutes. The next/prev button's text change depending on the route, as do their transitions (since the transition depends on the current state of the wizard). It's more or less a FSM