Question

I'd like to implement this statechart in Ember.js v1.5.x using Ember.Router, but I have problems with the concurrency and history mechanism.

Basically when I activate the Summary route/state I'd like to transition to No changes made and Transient state in the same time. How can I achieve this?

P.S. I know that e.g. stativus have these capabilities but don't know how to use it with Ember.js routing. An example would bee good.

(image source: Ian Horrocks: Constructing the User Interface With Statecharts p.153).

Was it helpful?

Solution

:)

Yeah statecharts are lovely and all, but Ember actually affords sub-states through computed properties.

I'm not overly familiar with state charts, and I'd really need to consume the resources (horrocks) you mentioned here (https://github.com/emberjs/ember.js/issues/4767#issuecomment-41458710) before I'd be fully conversant in the nomenclature of that particular example (which I can do if you'd like).

To that end, and having said that, please take my answer with a grain of salt, because I may not fully understand the context. I just hope to help.

So in Ember you have routes. Those routes explain the interface of your application. These will effectively be your states. Routes are not your actions, or events. They provide a URL for your app to present itself to the world.

So, state A seems to be presenting the Students. You have two sub-states in there... 0 students and >0 students. You would handle these with the same Route (call it StudentsRoute), because they're both about the same set of data, just different substates of it. The route would have a path called /students probably. At that point, you'd have a controller gets fed a model by the router (the list of students), so to that end, this controller would be an extension of Em.ArrayController.

This array controller (auto-named StudentsController, extends Em.ArrayController) automatically has a 'model', and that model, once resolved, is the students "array".

In StudentsController, you could easily have a computed property called zeroCount which represents the state of zero or not about the model. Computed properties automatically stay up to date. That'd be defined like this:

App.StudentsController = Em.ArrayController.extend({
  zeroCount: function() {
  // zeroCount is true if zero, otherwise false
    return this.get('model.length') == 0;
  }.property('model.length');
});

In your students template, you could conditionally render one of two sub-templates depending on this zeroCount state... you'd do that like this:

{{#if zeroCount}}
  {{partial "noStudents"}}
{{else}}
  {{partial "someStudents"}}
{{/if}}

Mind you, for this example, that'd be somewhat overkill... you probably don't need to render other templates (partials) like that.. there's an easier simpler way to do it because this is a common pattern in ember (rendering a list, and optionally rendering something else if there are no items in it, without needing the zeroCount property).

{{#each model}}
  <p>This renders against each student... <br>
  so if your students have a property called name, <br>
  then you could just write {{name}} and it'd render the
  students name</p>
{{else}}
  <p>This renders when there are no students</p>
{{/each}}

You'd put a delete link on each of those items... and the live bound properties handle all the states for you... (thus, when model has zero items in it, the template goes into the else block of the each... otherwise it goes into the main block).

The delete action, handled by something like Delete inside your #each model template (handlebars) directive goes to the controller and looks for an action inside of it called, unsurprisingly, delete... and that'd look like this:

App.StudentsController = Em.ArrayController.extend({
  actions: {
    delete: function(itemToDelete) {
      itemToDelete.delete();
      // assuming the model "class" understands delete
    }
  }
});

The edit state would have its own route... possibly a nested route on the students, called edit, possibly not depending on if you wanted the list to appear on the screen while the edit page appears...

The "changes made" state is effectively handled not on the route, but on the model... as it should be... the model is responsible for persisting the object graph, or telling the view and controller whether or not the model has changed (Ember Data, for example, afford isDirty as a state on each model instance that can tell you whether it has changed or not)...

Hopefully this whets your appetite. I recommend going through some of the examples on the Ember site... they really do help, and following the Ember TODOMVC app if you haven't checked that out...

Ember thrives on these kind of flow-based state driven UIs... check out Tom and Yehuda's keynote at confreaks if you haven't already... they talk about flows in exactly the same way you're talking about these states and sub-states.

Hope that helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top