javascriptruby-on-railsstimulusjs

Selectively load stimulus controller in Rails 7


Is there a way to selectively register a stimulus controller so it doesn't get registered on every page in Rails 7.

I have a stimulus controller stripe_controller.js that imports stripe-js:


    import { loadStripe } from "@stripe/stripe-js"

and this is causing stripe to generate an iFrame on every page of my site even when the controller is not connected.

My app/javascript/controllers/index.js is loading my controller:


    import { application } from "./application"

    import StripeController from "./stripe_controller"
    application.register("stripe", StripeController)

Is there a way to dynamically register instead of including it in the index.js file?


Solution

  • I eventually found a solution in the ImportMap Documentation :| https://github.com/rails/importmap-rails#selectively-importing-modules.

    Basically, you can move the register code from app/javascript/controllers/index.js to a new js file such as app/javascript/register.js.

    import { application } from "./controllers/application"
    
    import StripeController from "./controllers/stripe_controller"
    application.register("stripe", StripeController)
    

    Then you need to pin it to importmap.rb

    pin "register"
    

    Then you need to yield it into the the header, so if you don't already have something like <%= yield(:head) %> in your application.html.erb layout then add it. Now you can yield the register script on the ERB pages you need it like so:

    <%= content_for :head do %>
        <%= javascript_import_module_tag "register %>
    <% end %>