If you want state to be routable (i.e. reachable via a url), then it needs to be serializable and deserializable via ember's router. If state is transient and not routable, then it is probably best kept on the controller.
If you need to represent complex interface state across multiple models (say, for selecting items in a list), consider maintaining a controller-specific array of objects that wrap underlying data models. I think it's hackish to represent view state directly on models, especially if those models are used across multiple views.
For the example you provided, you might do something like this to hook up 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);
}
})
Note that you could also use a route such as "flights?cities=:cities&dates=:dates" but the above is probably cleaner and more SEO-friendly.
Expanded upon after Gabriel's comments: If you want to maintain an array of searches, each of which resides in its own tab, I'd recommend keeping the data for those searches in an application-level array (e.g. App.currentUser.activeSearches). My reasoning is that you don't want to have to recreate this data every time a user switches tabs. Instead, the router would retrieve this data in deserialize()
and then pass it as the context to connectOutlets()
. The view and controller to represent this data should be quickly re-constructed based upon this object when switching tabs. Let me extend my example from 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);
}
})