{"id":13624,"date":"2025-11-11T04:57:02","date_gmt":"2025-11-11T04:57:02","guid":{"rendered":"https:\/\/www.bacancytechnology.com\/qanda\/?p=13624"},"modified":"2025-11-12T11:26:14","modified_gmt":"2025-11-12T11:26:14","slug":"using-importmap-and-stimulus-in-rails-engine","status":"publish","type":"post","link":"https:\/\/www.bacancytechnology.com\/qanda\/ruby-on-rails\/using-importmap-and-stimulus-in-rails-engine","title":{"rendered":"Using Importmap and Stimulus in Rails Engine (Simplified)"},"content":{"rendered":"<p>If we&#8217;re building a <strong>Rails Engine<\/strong> and we&#8217;re using <strong>Importmap <\/strong>(instead of Webpacker or esbuild), here&#8217;s how we can connect our engine&#8217;s JavaScript, including <strong>Stimulus controllers<\/strong> to the main app:<\/p>\n<h3>Set Up our Engine\u2019s JavaScript Files<\/h3>\n<p>Inside our engine (my_engine), create a folder like this:<\/p>\n<pre class=\"lang:adddarkplain\">app\/javascript\/my_engine\/\r\n\u251c\u2500\u2500 application.js\r\n\u2514\u2500\u2500 controllers\/\r\n    \u251c\u2500\u2500 index.js\r\n    \u2514\u2500\u2500 hello_controller.js<\/pre>\n<h3>In hello_controller.js, define our Stimulus controller:<\/h3>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"ruby\">import { Controller } from \"@hotwired\/stimulus\"\r\n\r\nexport default class extends Controller {\r\n  connect() {\r\n    console.log(\"Hello from MyEngine!\")\r\n  }\r\n}\r\n<\/pre>\n<h3>Load Controllers<\/h3>\n<p>In controllers\/index.js, load our Stimulus controllers. We can do this with:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"ruby\">import { Application } from \"@hotwired\/stimulus\"\r\nimport HelloController from \".\/hello_controller.js\"\r\n\r\nconst app = Application.start()\r\napp.register(\"hello\", HelloController)\r\n<\/pre>\n<h3>Make Sure the JavaScript Gets Precompiled<\/h3>\n<p>In our engine\u2019s config (engine.rb):<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"ruby\">initializer \"my_engine.assets.precompile\" do |app|\r\n  app.config.assets.precompile += %w[my_engine\/application.js]\r\nend\r\n<\/pre>\n<p><span style=\"color: #ff0000;\">This makes sure Rails knows to include our engine&#8217;s JS when compiling assets.<\/span><\/p>\n<h3>Tell the Host App to Load our Engine\u2019s JS<\/h3>\n<p>In the host app\u2019s config\/importmap.rb, add:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"ruby\">pin \"my_engine\", to: \"my_engine\/application.js\"\r\nwe can also pin controller files if needed:\r\npin_all_from \"my_engine\/controllers\", under: \"my_engine\/controllers\"\r\n<\/pre>\n<h3>Use the Controller in our App<\/h3>\n<p>Now, in a view in our main app, we can use our engine&#8217;s Stimulus controller like this:<\/p>\n<pre class=\"lang:adddarkplain\">&lt;div data-controller=\"hello\"&gt;\r\n  Hello from the engine!\r\n&lt;\/div&gt;<\/pre>\n<p><span style=\"color: #ff0000;\">Tip: Let the Host App Start Stimulus (Optional)<\/span><\/p>\n<p>If we want the host app to be in charge of starting Stimulus, skip starting it in the engine. Then in the host app\u2019s application.js:<\/p>\n<pre class=\"lang:adddarkplain\">import { Application } from \"@hotwired\/stimulus\"\r\nimport \"my_engine\/controllers\"\r\n\r\nconst app = Application.start()\r\n<\/pre>\n<div class=\"qanda-read-box\"><div class=\"bg-light read-more-icon\"><img decoding=\"async\" src=\"https:\/\/assets.bacancytechnology.com\/qanda\/wp-content\/uploads\/2025\/04\/24061434\/read-txt.png\" alt=\"Also Read\"><p><\/p><h3>Also Read:<\/h3><a href=\"https:\/\/www.bacancytechnology.com\/blog\/hotwire-rails-tutorial\" target=\"_blank\">Hotwire Rails<\/a><\/div><\/div>\n","protected":false},"excerpt":{"rendered":"<p>If we&#8217;re building a Rails Engine and we&#8217;re using Importmap (instead of Webpacker or esbuild), here&#8217;s how we can connect our engine&#8217;s JavaScript, including Stimulus controllers to the main app: Set Up our Engine\u2019s JavaScript Files Inside our engine (my_engine), create a folder like this: app\/javascript\/my_engine\/ \u251c\u2500\u2500 application.js \u2514\u2500\u2500 controllers\/ \u251c\u2500\u2500 index.js \u2514\u2500\u2500 hello_controller.js In [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":13675,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"footnotes":""},"categories":[11],"tags":[],"class_list":["post-13624","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ruby-on-rails"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.bacancytechnology.com\/qanda\/wp-json\/wp\/v2\/posts\/13624"}],"collection":[{"href":"https:\/\/www.bacancytechnology.com\/qanda\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.bacancytechnology.com\/qanda\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.bacancytechnology.com\/qanda\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.bacancytechnology.com\/qanda\/wp-json\/wp\/v2\/comments?post=13624"}],"version-history":[{"count":3,"href":"https:\/\/www.bacancytechnology.com\/qanda\/wp-json\/wp\/v2\/posts\/13624\/revisions"}],"predecessor-version":[{"id":13676,"href":"https:\/\/www.bacancytechnology.com\/qanda\/wp-json\/wp\/v2\/posts\/13624\/revisions\/13676"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.bacancytechnology.com\/qanda\/wp-json\/wp\/v2\/media\/13675"}],"wp:attachment":[{"href":"https:\/\/www.bacancytechnology.com\/qanda\/wp-json\/wp\/v2\/media?parent=13624"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.bacancytechnology.com\/qanda\/wp-json\/wp\/v2\/categories?post=13624"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.bacancytechnology.com\/qanda\/wp-json\/wp\/v2\/tags?post=13624"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}