Search code examples
javascriptruby-on-railsruby-on-rails-7import-maps

Where to place Javascript used in one page only in Rails 7 with importmap


When using Rails 7 with import maps, where do I put code that should be executed by one view only?

Specifically, I have a view that needs to run some Javascript code on load. My Javascript looks something like this:

import {TheController} from "./TheController"

let controller = new TheController();

document.onreadystatechange = function () {
  if (document.readyState === 'complete') {
    controller.onLoad();
  }
};  

How do I setup the Javascript environment so that the document.onreadystatechange code is executed only by the desired view? (Everything almost works when I put this code in a file imported by application.js, but then it gets executed by every view.)

I suspect the answer is to create separate importmaps and importmap_tags; but, I can find any demonstrations of how to do that in Rails 7.


Solution

  • As @Azrklm points out, the answer is contained in this video https://youtu.be/PtxZvFnL2i0?t=1287 beginning at time 21:38.

    Suppose we have some JavaScript that we want to run only on a view called FancyView. Here are the steps

    1. Place the code unique to FancyView in its own file, say FancyView.js (and remove it from application.js, if necessary).

    2. Add a line for FancyView.js to the importmap: pin "FancyView"

    3. Add the line <%= yield :head %> to application.html.erb`. (This tells Rails that individual views/layouts may want to add additional information to the web page's head.)

      <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
      <%= javascript_importmap_tags %> <%# This loads application.js %>
      <%= yield :head %>
      
    4. Add a javascript_import_module_tag to the view:

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