Ember.js - where should the state of the interface be stored?

Is there an official story about where the state of the interface (as opposed to the state of the saved model) should live in the Ember.js application?

The User Response section of Router Documents shows an example of delegating click events on a showPhoto photo, but having a show model in itself seems like an undesirable mix of problems.

I understand that in many cases, the state must be stored in the router, so that the state of the interface is displayed in the URL and restored if you refresh the page or send the URL to someone. But what about a non-hierarchical state, such as a list of items selected on a page?

Ideally, this type of state will be serialized as request / hash parameters (for example: http://www.hipmunk.com/flights/QSF-to-NYC#!dates=Sep15,Sep16p1;kind=flight&locations=QSF,YYZ&dates=Sep15, Sep23 ~ tab = 1 ), but as far as I know, the router does not offer this functionality, right?

In BackboneConf, Jeremy Ashkenas said the right way to do this in Backbone is to simply save the state on the model (he had an example of a model with a β€œselected” field). But I believe that Tom Dale said that he did not think it was a good idea, and not how to do it in Amber. Unfortunately, I do not remember him mentioning how this should be done.

+7
source share
1 answer

If you want the state to be routable (i.e. accessible via a URL), it must be serializable and deserializable through the ember router. If the state is transient and not routable, then it is probably best to keep it on the controller.

If you need to imagine the complex state of an interface for several models (for example, to select items in a list), consider supporting an array of controller-specific objects that wrap the underlying data models. I think it’s hacking to represent the state of a view directly on models, especially if these models are used in multiple views.

In the above example, you can do something similar to connect a complex route:

Ember.Route.extend({ route: "flights/:cities/dates/:dates", serialize: function(router, context){ return {cities: context.get('cities'), dates: context.get('dates')}; }, deserialize: function(router, params){ // return a context object that will be passed into connectOutlets() return {cities: params.cities, dates: params.dates}; }, connectOutlets: function(router, context) { // pass the context from deserialize() in as the content of a FlightController router.get('applicationController').connectOutlet('flight', context); } }) 

Please note that you can also use a route such as "flights? Cities =: cities and dates =: dates", but higher is probably cleaner and more optimized for SEO.


Extension after Gabriel's comments. If you want to save an array of queries, each of which is on its own tab, I would recommend storing the data for these searches in an application-level array (for example, App.currentUser. ActiveSearches). My reasoning is that you do not want to update this data every time the user switches tabs. Instead, the router will retrieve this data in deserialize() , and then pass it as a context to connectOutlets() . The view and controller for presenting this data must be quickly rebuilt based on this object when switching tabs. Let me expand my example above:

 Ember.Route.extend({ route: "flights/:cities/dates/:dates", serialize: function(router, context){ return {cities: context.get('cities'), dates: context.get('dates')}; }, deserialize: function(router, params){ // find or create a "Search" object that contains the filters and results, // which will be passed into connectOutlets() return App.currentUser.findOrCreateSearch({cities: params.cities, dates: params.dates}); }, connectOutlets: function(router, context) { // pass the context (a search object) from deserialize() in as the content of a FlightController router.get('applicationController').connectOutlet('flight', context); } }) 
+4
source

All Articles