Backbone.js - where to store state information?

13,730

Solution 1

Why don't create a state model to store and describe the current state? I don't think that is wrong. Since the current state involves more than one model I think it's reasonable to create a state model to store and receive the current state.

The controller could then communicate with the state model to get the current state. The UI states should be stored in the corresponding model though. The state model knows which book and which page and then the book and page models keep track of their current UI states.

Solution 2

Don't limit your Backbone apps to Backbone constructs. If you find that your app needs some functionality that doesn't fit well into one of Backbone's constructs, don't shoehorn it into one just for the sake of keeping everything in Backbone.

I've found this backbone boilerplate to be helpful in this respect. It sets up modules for you and provides you with an app object that extends Backbone.Events (like in the previously-linked article). This app object can be used to store instantiated models, views and controllers/routers, and you should feel free to add your own non-backbone modules to the app object, to take care of responsibilities that don't fit perfectly into one of the Backbone constructs.

Share:
13,730

Related videos on Youtube

nrabinowitz
Author by

nrabinowitz

I'm a data visualization developer with a background working with non-profit and public sector organizations. I like APIs, large-scale Javascript applications, Open Source licenses, and complex problems involving the intersection of people, organizations, and technology.

Updated on June 07, 2022

Comments

  • nrabinowitz
    nrabinowitz almost 2 years

    I'm new to Backbone.js, and I'm trying to figure out where state variables should live. My use case:

    I have an application that provides a reading interface for a book (I know, classic example, right?). My models are Book and Page with collection classes for each. The structure of the application looks roughly like this (forgive the ASCII visio):

    +------------+
    | Controller |
    +------------+
        |      Views                 Models
        | +--------------+      +----------------+
        |-|  IndexView   |------| BookCollection |
        | +--------------+      +----------------+
        |                               |
        | +--------------+      +----------------+
        +-|   BookView   |------|     Book       |
          +--------------+      +----------------+
           |                            |
           | +--------------+           |
           |-|  TitleView   |-+         |
           | +--------------+ | +----------------+
           |                  +-|     Page       |
           | +--------------+ | +----------------+ 
           +-|   PageView   |-+
             +--------------+ 
    

    That is, the Controller instantiates and coordinates two views, IndexView and BookView, backed by the models. The BookView instantiates and coordinates a set of subviews (there are actually more than shown here).

    State information includes:

    • the current book (pointer or id)
    • the current page (pointer or id)
    • other UI state variables, such as whether images on the page are visible or not, whether other widgets are open or closed, etc.

    My question is, where should this state information live? Possible options include:

    • The models, which could be state-aware. This makes some sense, since they're intended to store data and views could listen for state changes, but it doesn't seem like this fits the intended Backbone.js pattern, and wouldn't always make sense (e.g. turning image on in the PageView should apply to all pages, not just the current one)

    • A special singleton model intended to hold state information. Again, makes sense, easy to listen to, all the views could bind to it - but again, this seems outside standard MVC.

    • The views, who are responsible for the UI state - but this would require views to be aware of each other to get state info, which seems incorrect

    • The controller, which should route the application between states - this makes sense, but it implies a slightly odd round trip, e.g. User selects "Show Images" --> View event listener is called --> View informs Controller --> Controller updates state --> Controller updates View (rather than the simpler User selects "Show Images" --> View event listener is called --> View updates)

    I guess in some ways this is a generic MVC question, but I'm having trouble getting my head around it. What part of the application should be responsible for saving the current state?

    UPDATE: For future reference, I used a global singleton State model for this problem. The UI flow goes like this:

    1. View UI handlers do nothing but update app.State
    2. My routers also do nothing but update app.State - they're essentially specialized views that display and react to URL changes
    3. Views listen to changes on app.State and update accordingly

    My app is Open Source - you can see the code on Github. The relevant piece here is the State model, which I've extended to deal with (de)serializing state for the URL.

    • Raynos
      Raynos over 12 years
      There is no Controller in backbone 0.5
    • nrabinowitz
      nrabinowitz over 12 years
      Well, yes, I have a Router class I'm calling Controller. It's still basically intended to perform the function of a controller, right?
    • Raynos
      Raynos over 12 years
      not really. In terms of classical MVC you should view the View as a classical Controller. It's best not to try and think of classical MVC when doing backbone. In terms of your question current book goes into the AppView, current page goes into the Book, the rest goes into AppView. AppView is a special singleton view if you will
    • nrabinowitz
      nrabinowitz over 12 years
      Wouldn't the current page go into BookView, not Book, by that logic?
  • nrabinowitz
    nrabinowitz over 12 years
    This is more or less the way I've decided to go, but I'm ditching the controller altogether - views update the state model on UI events, then listen for state updates to update the UI, and the router does the same for the URL.
  • Ragnar
    Ragnar over 12 years
    Cool. I was struggling with similar problem in a rails app. Functionality that didn't really fit in any of the existing models or controller was solved with new models that also helped the app staying "RESTful".
  • nrabinowitz
    nrabinowitz over 12 years
    Thanks for the links. This is actually not too far from what I did - e.g. see my app initialization, which is pretty similar to what's linked. But Backbone does help with a State model, in terms of events and listeners. You can see my implementation here.