Launch a Turbo Modal with URL Params Using Stimulus

Having certain screens in a modal (or slide over) on top of your app can be great to give that context the user needs for the action they want to take. Think: settings for a page they are editing, a notifications list or a list of tasks to be done.

This is really easy to create with Rails and Turbo (and even easier with Rails Designer’s ModalComponent or SlideOverComponent) 💡). But what if you want to link to that screen from an email or allow your users to share it with their team, like: example.com?v=settings. No problem with a small, single-purpose Stimulus controller!

Yes, the beauty of Turbo Frames is you can link to a standalone page for, say, the settings of a page, but that would remove the context of the page a modal gives. So that is what’s on the menu today. Let’s get started! 🚀

Another tip: Rails Designer has this controller, along with a complete library of UI components for Rails, for you!

How to Open Turbo Modal Using URL Params and Stimulus

To me the beauty of Stimulus is it allows you to write small, maintainable controllers that are typically concerned with one purpose. That’s also the case for this controller.

I assume you have a Rails app ready. I also assume you have a way of showing a modal or slide over through a turbo frame. If not, check this article on how to create a modal with Rails and Hotwire.

Let’s create the basics for the Stimulus controller first: bin/rails generate stimulus turbo_frame_load. Then set up some value properties: paramName (defaulting to “v”) and the paths. The latter value object is where the mapping between a value and a path is set.

import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  static values = {
    paramName: { type: String, default: "v" },
    paths: Object
  };
}

Then onto the connect() function, as the modal/slide over needs to be set every time an URL is loaded.

import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  // …
  connect() {
    this.element.src = this.pathsValue[this.#param];
  }
}

Easy enough! It sets the element’s src attribute with the value matching this.#param. Let’s create that private function.

import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  // …

  // private

  get #param() {
    return this.#params.get(this.paramNameValue);
  }

  get #params() {
    return new URLSearchParams(window.location.search);
  }
}

(if you haven’t seen the // private line or the # before those function names, go read this article on properly structuring your Stimulus controllers).

get #param() calls get #params() that creates a URLSearchParams object from the query string of the current page’s URL, allowing easy access and manipulation of URL parameters.

Now set up the controller to the turbo-frame element:

<%= turbo_frame_tag "modal", data: {controller: "turbo-frame-load", turbo_frame_load_paths_value: {settings: settings_path, notifications: notifications_path}} %>

The important part is the paths value: {settings: settings_path, notifications: notifications_path}. Each key should be unique and its value should be a path that can be loaded in the turbo_frame_tag.

With that line in place, you can load http://localhost:3000?v=settings and the settings are loaded in the modal. Sweet!

But let’s make one improvement:

import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  // …

  connect() {
    if (this.#isInvalidParam) { return; }
    // …
  }

  // private

  get #isInvalidParam() {
    return !this.#param && !this.pathsValue[this.#param];
  }

  // …
}

This will check if an expected param is valid ánd if it is present in the paths values object.

And that’s all you need to load screens in a modal or slide over upon page load. Not more than 10 lines of JavaScript. Don’t you love Stimulus? 😍

Did you know Rails Designer comes with a turbo_frame_load controller.

Get UI & Product Engineering Insights for Rails Apps (and product updates!)

Published at . Last updated at . Have suggestions or improvements on this content? Do reach out.

UI components for Ruby on Rails apps

$ 129 one-time
payment

Get Access
  • One-time Payment

  • Access to the Entire Library

  • Built for Ruby on Rails (inc. Rails 8)

  • Designed with Tailwind CSS and Enhanced with Hotwire

  • Updates for 12 months