Use the browser buttons to navigate inside your app

If your app shows a list of items usually you'd want to display a secondary view which will allow the user to edit the selected item for example.

A standard way to navigate inside a web app is by using the back and forward buttons. In Retool this is not supported right now.

Here's an example app that makes use of the browser navigation buttons to switch between two views of a tabbed container.

Video:

Browser Navigation

Public app: https://vladi.retool.com/embedded/public/b386f285-2e06-4a4b-a79a-1d5d182685f3

Source: Dropbox - History%20test.json - Simplify your life

How it works

Below is the main script. It relies on the history API to make everything work. (History - Web APIs | MDN).

Add this as a global JavaScript inside your app's Scripts and styles window:

function handleSecondaryView(key, callback) {
  const secondaryState = `${key}-secondaryState`
  const lastPopstateHandlerKey = `${key}-lastPopstateHandler`
  
  history.pushState(secondaryState, null);
  window.removeEventListener('popstate', window[lastPopstateHandlerKey]);

  function onPopstate(event) {  
    callback(event.state === secondaryState)
  }

  window.addEventListener('popstate', onPopstate);
  window[lastPopstateHandlerKey] = onPopstate
  
  callback(true)
}

Add this JS query whenever a table row is selected:

window.handleSecondaryView('users', isSecondaryViewOpened => {
  if (isSecondaryViewOpened) {
    tabbedContainer.setCurrentView('editUser')
  } else {
    tabbedContainer.setCurrentView('users')
  }
})

You can still have your own back button inside your app but it has to use the history api in order to play well in the browser navigation.

Use this JS query for your custom back button:

window.history.back()

Why not just make two apps?

You can indeed get this behaviour without any additional scripts if the list and the details views are two separate Retool apps. Switching between apps takes more time, however, as the new app has to load, so it is not a great experience in this case .

4 Likes

I'm encountering an error related to navigation. The error mentions using a blocker on a POP navigation that was not created by @remix-run/router. Any suggestions on how to properly handle navigation and browser back buttons?

Hi @slaw!

Thanks for reaching out! Do you mind sharing how you encountered that error message and sending over any screenshots if you're still running into it?

For overall best practice on handling navigation within your app, you can:

  1. Implement the Navigation or Button component. You can then use the onClick or onChange event property to define the action to execute.
  2. Use URL params in your Retool app. This approach enables binding the app's state, such as the active tab in a tabbed container, to a URL query parameter. The previous state can then be restored by reading this parameter when reloading the page. Here is how to set up URL query params.

Let me know if I misunderstood anything or if you have any additional questions!

I'm trying this option but if you are on a page and use the go-to app event handler, when you are on the app already, the url Params aren't updated.
I've resorted to using Goto url and manually adding the url Params but that doesn't seem ideal.
Am I missing something?
Thanks.

Hi @jason3w,

So far in my testing, I'm seeing the same behavior for go to url and go to app (where the url hash params get updated). We have a bug report on file to enable force reloading the page when triggering go to app events in the same app - I'll let you know if it gets fixed

1 Like