Skip to content

Instantly share code, notes, and snippets.

@aubricus
Last active May 2, 2016 20:18
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aubricus/ffdb2b40250614808018ccf268b5fa00 to your computer and use it in GitHub Desktop.
Save aubricus/ffdb2b40250614808018ccf268b5fa00 to your computer and use it in GitHub Desktop.
Micro-visual-state-transition mechanic
define(function (require, exports, module) {
var _ = require("underscore");
var $ = require("jquery");
var backbone = require("backbone");
var marionette = require("marionette");
var UploadImagesModalView = marionette.LayoutView.extend({
validTansitionStates: ["initial", "activity", "valid", "invalid"],
/* code redacted */
/**
* transition to a state, must be a valid state
* Uses marionette "triggerMethod" to enable dynamic
* function calls based on the `state` param
*
* @param {String} state
* @event `"state:<state>`, `on<State>`
* @event `"state:changed"`, `onStateChanged`
*
* @see `this.validTransitionStates`
*/
transitionToState: function(state) {
this.triggerMethod("state:changed", this, state);
this.triggerMethod("state:" + state, this);
},
/**
* triggered by `this.transitionToState`
* @throws {Error, "ValueError"} when an invalid state is passed
*
* @see `this.validTransitionStates`
*/
onStateChanged: function(sender, state) {
if(this.validTansitionStates.indexOf(state) == -1) {
throw new Error("ValueError, unsupported transition state value: " + state);
}
this._state = state;
},
onStateInitial: function() {
this.ui.submitBtn
.prop("disabled", true)
.attr("value", "Upload");
},
onStateActivity: function() {
this.ui.submitBtn
.prop("disabled", true)
.attr("value", "Please Wait...");
},
onStateValid: function() {
this.ui.submitBtn
.prop("disabled", false)
.attr("value", "Upload");
},
onStateInvalid: function() {
this.ui.submitBtn
.prop("disabled", true)
.attr("value", "Upload");
},
/* example call to transition */
maybeSubmit: function() {
this.transitionToState("activity");
/* code redacted */
},
/* code redacted */
});
});
@aubricus
Copy link
Author

aubricus commented May 2, 2016

A micro-transition state handling pattern.

Here we're leveraging the super nice triggerMethod function from Marionette. triggerMethod works just like trigger in that it dispatches an event but it also automatically calls a method ("event:name" converts to: this.onEventName) on the object that called it. This enables simple state handling functions without all the complex event callback registration / de-registration (Marionette views also clean their events automatically, no zombie views!)

This pattern does a good job of encapsulating our visual state code into small, testable bits and:

  • Will throw an error if it encounters an invalid state
  • Dispatch a "state:<state>" event and companion trigger method onState<Name>

It however does not:

  • Provide any validation between states (i.e., state A can transition to any state)
  • Provide any indication of when a state has started, in progress, or finished.

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