Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 34 You must be signed in to star a gist
  • Fork 13 You must be signed in to fork a gist
  • Save andrewdeandrade/1112194 to your computer and use it in GitHub Desktop.
Save andrewdeandrade/1112194 to your computer and use it in GitHub Desktop.
Backbone.js Wizard
namespace.views.MyWizard = Backbone.Views.extend({
initialize: function() {
_.bindAll(this, 'render', 'wizardMethod');
}
render: function() {
this.wizardMethod();
return this;
},
wizardMethod: function() {
var myModel = new MyModel;
var steps = [
{
step_number : 1,
title : "Title of Step 1",
instructions : "Instructions or description of what the user needs to do for this step",
view : new namespace.views.WizardStepOne({ model : myModel })
},
{
step_number : 2,
title : "Title of Step 2",
instructions : "Instructions or description of what the user needs to do for this step",
view : new namespace.views.WizardStepTwo({ model : myModel })
},
{
step_number : 3,
title : "Title of Step 3",
instructions : "Instructions or description of what the user needs to do for this step",
view : new namespace.views.WizardStepThree({ model : myModel })
}
];
var view = new nameplace.ui.Wizard({
model : myModel,
steps : steps
});
$("#current_step").html(view.render().el);
}
});
namespace.ui.Wizard = Backbone.View.extend({
id: 'wizard',
events: {
"click #next_step_button" : "nextStep",
"click #prev_step_button" : "prevStep"
},
initialize: function() {
_.bindAll(this, 'render');
this.currentStep = 0;
},
render: function() {
var t = template('ui/wizard');
$(this.el).html( t({}) );
this.progressIndicator = this.$("#progress_indicator");
this.title = this.$("h2#step_title");
this.instructions = this.$("p#step_instructions");
this.currentStepContainer = this.$(".current_step_container");
this.nextStepButton = this.$("#next_step_button");
this.prevStepButton = this.$("#prev_step_button");
this.renderCurrentStep();
return this;
},
renderProgressIndicator: function() {
this.progressIndicator.empty();
_.each(this.options.steps, _.bind(function(step) {
var text = "(" + step.step_number + ") " + step.title + ">>> ";
var el = this.make('span', {}, text);
if (step.step_number == this.currentStep + 1) $(el).addClass('active');
this.progressIndicator.append(el);
}, this));
},
renderCurrentStep: function() {
var currentStep = this.options.steps[this.currentStep];
if (!this.isFirstStep()) var prevStep = this.options.steps[this.currentStep - 1];
var nextStep = this.options.steps[this.currentStep + 1];
this.title.html(currentStep.title);
this.instructions.html(currentStep.instructions);
this.currentView = currentStep.view;
this.currentStepContainer.html(this.currentView.render().el);
this.renderProgressIndicator();
if (prevStep) {
this.prevStepButton.html("Prev: " + prevStep.title).show()
} else {
this.prevStepButton.hide();
};
if (nextStep) {
this.nextStepButton.html("Next: " + nextStep.title);
} else {
this.nextStepButton.html("Finish");
};
},
nextStep: function() {
if (this.currentView.validate()) {
if (!this.isLastStep()) {
this.currentView.validate();
this.currentStep += 1;
this.renderCurrentStep();
} else {
this.save();
};
};
},
prevStep: function() {
if (!this.isFirstStep()) {
this.currentStep -= 1;
this.renderCurrentStep();
};
},
isFirstStep: function() {
return (this.currentStep == 0);
},
isLastStep: function() {
return (this.currentStep == this.options.steps.length - 1);
}
});
<header>
<div id="progress_indicator"></div>
<h2 id="step_title"></h2>
<p id="step_instructions"></p>
</header>
<div class="current_step_container"></div>
<footer>
<div id="buttons">
<a id="prev_step_button" class="button">Prev:</a>
<a id="next_step_button" class="button">Next:</a>
</div>
</footer>
@KingAndrew
Copy link

Very easy to understand. I do have 1 question. Is their any special meaning to line #3 in wizard.js: id: 'wizard',?
I guess what I'm asking is do I have to have a div id='wizard' in the mark-up that this needs to match? I havent seen id used/set much at all.

@jonathan-beebe
Copy link

You've included this.currentView.validate() within namespace.ui.Wizard.nextStep, however .validate() is not a method of Backbone.View. Have you purposely left this as an exercise for the reader? Or perhaps you meant this.currentView.model.validate()?

Copy link

ghost commented Dec 2, 2013

I am a beginner in backbone js. Can I please get a tutorial on this since I am finding it a bit difficult using this wizard in my own app.

@markcline
Copy link

@somethingkindawierd Presumably view.validate() is a custom method that only validates the data on that page (since validating the whole model would fail until you get to the end). It's too bad this gist doesn't include the views.

@ayxos
Copy link

ayxos commented Aug 9, 2014

thanks! i needed something like this, you're awesome

i've made some changes:
http://ayxos.com/backbone-wizard/
https://github.com/cybermarkus1/backbone-wizard

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment