Opening modals using query params in Ember.js
Basic example
In modern web design, modals are a powerful tool that allows content to displayed to the user in-context without navigating to a different page.
In most implementations, modal components take in a flag which controls its open/closed state, and a callback which is called when the “Close” button is clicked. In other words, the open state of the modal is controlled by a parent component. Let’s say we have a button component that when clicked on should open a modal. Here’s a super simplified implementation:
And in our component/route logic, we define the properties and actions:
Thanks to Ember’s powerful “tracked properties” mechanism, we can use simple property assignment to update the isOpen
property in our click handlers, and the template will be updated to use the new isOpen
value. In this case, clicking on our Button component will set the isOpen
property to true, which will open our modal. If you’re not familiar with the @tracked
and @action
syntax, you can read up about them in the super helpful Ember Guides.
Supporting deeplink & query parameter
Now let’s say instead of manually clicking on a button to open the modal, we want to allow users to deeplink to the page with the modal already opened. This is a common use case, especially when the user navigates from a different page and we want to show some special content (e.g. promotions) when they land on the page.
A common way to handle this is to use a query parameter to indicate the modal open state. Let’s say our domain is www.ourawesomepage.com
. We have an “About” page, where we want to open the modal, so the full deep link can be www.ourawesomepage.com/about?openModal=true
. In Ember.js, to handle query parameters on a route, we have to define them in the controller for that route:
Now when the user navigates to www.ourawesomepage.com/about?openModal=true
, the openModal
property will be set to true
in our about route.
The next step is to change our above component logic to use this openModal
property to control the modal state, instead of using a property defined in the component. Luckily, Ember provides us a way to access query params of a route directly from a component, by using RouterService. This is a public Ember API that we can inject into the component, allowing us to access the global router state.
Now we can refer to the router within the component through calling this.router
. The router service has a currentRoute
property, which contains queryParams
property. We can leverage this to transform our previous isModalOpen
tracked property to be a getter instead, which derives its value from the route’s query params:
Finally, we also need to change our previous openModal
and closeModal
actions, since we no longer update the isModalOpen
property directly. Instead, now clicking on openModal
should append an openModal=true
query parameter to the currentURL
. Luckily, the router service has just the right method for that. By calling this.router.transitionTo
and passing in an object with the key queryParams
, we stay on the same route while appending the passed-in query param:
Now this works as expected! If we’re on www.ourawesomepage.com/about
, clicking on the button will append openModal=true
to the URL, resulting in www.ourawesomepage.com/about?openModal=true
without navigating away. Since our isModalOpen
getter gets the value of the openModal
query param in the URL, it will now return true, and our modal will open. Closing the modal will invoke our closeModal
callback, which sets the openModal
query param to null
, and will result in our URL being www.ourawesomepage.com/about
again. See the below for our complete component JS code:
And that’s it!
In this blog post we started with opening a modal in Ember.js using the state maintained within a component, then progressed to using query params to control modal state, and using Ember’s RouterService
to access and change the query param in the URL. Let me know your thoughts in the comments below, and hope to see you all in the next blog post!
References
Ember Guides page on query params
Ember Guides page on tracked properties and component actions
tags: Ember,front-end,technical