Create dynamic dependant dropdowns with Javascript in Rails 6.1.4
Tags: rails, javascript, webdev, tutorial
Published: 2022-02-03 09:08:34

<img src="https://blog.rafaljaroszewicz.com/wp-content/uploads/2022/01/Dependant-dropdowns.gif" alt="a gif showing final effect" /><figcaption>What we want to do here</figcaption></figure></div>

<p>I managed to pull this stunt off in an <a rel="noopener" href="https://github.com/marelons1337/kapturek" target="_blank">app</a> I'm working on. Let's say we want to have a payment module. On top of the form we have three dropdowns. To make things easier for the user, I want these dropdowns to be dependant, so first I choose the building, then another dropdown only server me flats that actually belong to the building and finally after choosing a flat, I will only be able to choose tenant that is living there.</p>

<p>Key points:</p>

<ol><li>Flat and Tenant dropdowns are empty until previous dropdown has changed.</li><li>After Building and Flat dropdown change, I want to fetch the data for next dropdown.</li><li>I want to use the data from fetch to fill out dropdowns.</li></ol>

<p>I'm setting up my arrays in the controller so I can access all the data in my view.</p><br>
{% gist https://gist.github.com/marelons1337/fdb206fde217e1327a3033220fbb2dd6 %}

<p>Now, if I want to fetch any data from the server I will need an endpoint that will allow me to access the data in JSON format so I can easily parse it and fill my dropdowns with it.<br>First, I create entries in my config/routes.rb file.</p><br>
{% gist https://gist.github.com/marelons1337/75462b721ff07e33fbf7d8454d036b4a %}

<p>That will reflect my actions in controllers:</p><br>
{% gist https://gist.github.com/marelons1337/b4c61769a484eeb6c7395b00616ad2d9 %}

<p>Now that I have my backend setup, I can proceed with the front.</p><br>
{% gist https://gist.github.com/marelons1337/b3ce5c9f7e52efd3138d75cd4efe38aa %}

<p>Here I have my dropdowns that I need to fill out dynamically.</p>

<p>At the time of writing this post, Rails 7 has already been released, but I already started my app in 6.1.4 and managed to understand a fraction of webpacker so I decided to stick with it. My JS code is inside javascript folder.<br><code>app/javascript/forms/fetch_building_data.js</code></p>

<p>Also, I added the require statement in <em>application.js</em><br><code>require('forms/fetch_building_data')</code></p>

<p>Here, I load my variables as soon as <em>turbolinks:load</em> is finished. That's the correct way of adding this handler, because if you try to add <em>DOMContentLoaded</em> or <em>load</em> it won't work. Rails way🛤.</p>

<p>Because I'm also using this script on Tenants view used to create them to have only two dropdowns (for Building and Flat) I have bundled this code into one file.<br>Now, first of all I set up length of dependant <code>select tags</code> to 1, that way only my placeholder will be available until you actually choose something. The rest of the function takes care of collecting the input from the dropdown<br><code>buildingSelect.addEventListener('input', function (event)</code><br>and storing it <code>let buildingId = event.target.value</code><br>Functions at the bottom create options for my select and append them.</p><br>
{% gist https://gist.github.com/marelons1337/ac0f35605e2d7daf47f65f7400973d0b.js %}

<p>That's it.</p>