How to persist application state between route transitions?

Hello,
What I’m trying to say is how to have a navigation bar like in here: https://koding.com/ ?
basically… when you go to another page using the top navigation buttons the other pages’ state is saved and when you return to them you can continue from where you were… you can also right click on the a nav element and choose close to close it definitively… it will be interesting if it can be done in ember

One approach is to use Ember Data, with a Local Storage Adapter if you’re only storing state locally, and query the store when you re-open the relevant routes. Models can represent both data and application state. You can selectively specify the adapter (see guide) so you can use different adapters for state-related models versus data.

Another approach, to persist state like filtering/sorting options, will require that state is reflected in properties in the Controller and/or View for a page, and then the values can be persisted in session storage (either continually as changed, or when the Controller’s willDestroy or the View’s willDestroyElement hook fires) and loaded from storage when returning (e.g. in the Controller and View init hooks), with fallback to defaults. I’m doing this in one of my projects to save the sizes of resizable components, and the last used filters for various tables.

1 Like

Thanks for your detailed answer… I think I’ll use your second approach…
however, surprisingly, koding.com is not using the localstorage in their website… do you have any idea of how they’re handling this?

I can’t log in to use koding.com, but the UI in the video looks very sophisticated. They’re probably keeping the different views open in DIVs until closed definitely, but hidden and put into a “sleep” state when the user clicks away to a different view, rather than rebuilding each view from some persisted state when the user returns.

Ember views can be complex, built up from components and even including other views embedded using {{render}} and {{view}} helpers. If you wanted to render multiple views simultaneously in different DIVs and use some UI/tab design to switch between them, that may be possible, though I think that kind of tabbing it’s not what Ember is geared toward. The Ember router is a core feature and it’s meant to be used – displaying different views at different routes, which are built and torn down as the user navigates around the app.

On the other hand, Zendesk is based in Ember and allows multiple tickets to be open in different tabs within the app. I would recommend using the Ember Inspector to poke around. On quick glance I can tell you they’re using a TabController that controls a TabsView at the top, and within the MainPaneView they have multiple TicketViews open, one per ticket. There’s also something called SwappableView. I’m guessing they use an {{#each}} helper to render multiple swappable views, one per open ticket, and separately render the tabs that manage which is brought to the foreground.

The question here seems to be “how can I persist application state between route transitions?” The answer above is about persisting application state across sessions instead. localStorage is for cross-session storage and will work for persisting across route transitions but it’s sort of like hammering a nail with a sledgehammer. Cross-session persistence also is not desirable in all cases.

I’m also interested in approaches for persisting state across route transitions. localStorage is not a good answer for me. I’ve attempted to store application-level state in the application controller, but that doesn’t always seem correct. Always having to look up the stored properties with

this.controllerFor("application").fooPersistedProperty

for instance feels wrong. I almost want to start storing application-level variables in the window namespace (or something like window.appVars), since that would work too. but it also seems like it’s abusing something or that ember should be providing a service for this.

1 Like

you’re right… changed the title so that it makes sense and also to be found more easily…
and using localstorage also feels like breaking the ember way of having a single source of truth… but I think it’s what I’ll be using for my app…
I can’t figure out a more appropriate way… :confused:

I’m a newcomer of ember that just started building my study project, and I’m considering using state machines (like ember-states) to organize my controllers’ states and store every current state as a string in query params.

For my current understanding, query params can be persistent across routing transitions, and they enjoy the excellent binding mechanisms ember provides.

Actually as a noob I’m not sure what I’m suggesting, or if it works at all. Is it a possible solution? Thanks for any correction.

I think this is already used in discourse… when we visit a topic for example and then return to the homepage we find it the way we left it…
I guess I should read discourse’s source

Controllers are the correct way to store application state - definitely don’t use “window” for this. You would ideally use the appropriate controller for your state. For example if you have a current user and some current tabs, you would store the current user as the content property of the currentUser controller, which would be extended from ObjectController, and the tabs as the content property of the tabs controller, which would be extended from ArrayController.

You can access these controllers using controllerFor in routes, or using the needs mechanism in other controllers.

3 Likes