States / Common options

There are several common options you can pass to each state manager when defining states in your component. Options are passed inside an options object like this:

this.states = [
  "action", { ...options go here },
  // StateActionManager declarations...

  "display", { ...options go here },
  // DisplayStateManager declarations...
];

State-manager-specific options were discussed before when StateActionManager and DisplayStateManager were described. Here, we'll discuss the options that can be used with any state manager.

pick_states_with_longest_definition_only

Default value: true

By default, StateManager will follow the specificity rule. To be more precise: if it finds that two state definitions match current state and one of these state definitions has all of the attributes and values of the other one, but also contains some other attributes and values (meaning, that definition is longer), it will only pick the one with the longest set of attributes. For example given these two declarations match current state:

this.states = [
  "action", {},
  [{ age: { more_than: 21 }}, "transition1"],
  [{ age: { more_than: 21 }, country: "United States"}, "transition2"]
];

only "transition2" will be invoked.

While this is useful, it might not always be desirable, thus you can change this behavior by setting the pick_states_with_longest_definition_only option to false:

this.states = [
  "action", { pick_states_with_longest_definition_only: false },
  [{ age: { more_than: 21 }}, "transition1"],
  [{ age: { more_than: 21 }, country: "United States"}, "transition2"]
];

Now, both "transition1" and "transition2" will be invoked.

debug

State declarations may get pretty complicated. Unit testing doesn't help with declarative statements too much because the tests would simply mimic what's written in state declarations. More often than not you'd want to explicitly see which states have been entered or exited and find a mistake in your declarations by manually testing your interface in the browser. The debug option allows you to print all the information you might need with regards to states into the browser console. To enable debugging, you pass an object containing some sub-options which would tell your StateManager instance exactly what debug information you want to see in your browser console:

this.states = [
  "action", { debug: { log: true, exit_states: true, enter_states: true, transitions: true }},
  // ...
];

  • log is a convenience switcher. You may temporarily enable or disable logging without removing your other logging preferences.
  • exit_states enables or disables logging of exit states.
  • enter_states enables or disables logging of enter states.
  • transitions enables or disables logging of transitions.

To be clear, the logger prints into the console every time your component changes state or StateDispatcher.applyTransitions() is otherwise called. Very often you might see that no states were entered or exited and no transitions applied - this doesn't mean the component itself hasn't changed its state - it only means that it changed its state in such way that no in or out transitions were matched against the new state of the component.