0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Rails7で動的に連動するセレクトボックスを作ろう!

Posted at

はじめに

親のカテゴリーを選択すると、子のカテゴリーの中身が選択された親のカテゴリーによって変わるようなセレクトボックスの作り方です。 

こちらの記事が動画付きで説明されていてイメージしやすいと思います。 

バージョン

  • Ruby 3.1.3
  • Rails 7.0.4

モデル

モデルはCategory(親要素)とSubCategory(子要素)の2種類で、関連付けされています。

category.rb
class Category < ApplicationRecord
    has_many :sub_categories
end
sub_category.rb
class SubCategory < ApplicationRecord
    belongs_to :category
end

View

セレクトボックスは使い回しできるようにパーシャル化しています。

_selectbox.html.erb
<%= form_with url: category_search_path, local: true, method: :get do |f| %>
    <div class="category-select">
        <%= f.collection_select :category, Category.all, :id, :name, include_blank: "カテゴリーを選択してください" %>
    </div>
    
    <div id="sub_category">
        <%= f.select :sub_category, [], include_blank: "---", class: "default-sub-category-select" %>
    </div>
    
    <%= f.submit "検索", class: "btn btn-primary" %>

    <% Category.all.each do |category| %>
        <template id="sub-category-of-category<%= category.id %>">
            <%= f.collection_select :sub_category, category.sub_categories, :id, :name, include_blank: "サブカテゴリーを選択してください" %>
        </template>
    <% end %>
<% end %>

はじめに全ての子要素のセレクトボックスをtemplateで用意しておき、親要素が選択された時にjavascriptで操作して必要なhtmlを取得するという魂胆です。

Javascript

今回は使い方がわからなかったので勉強のために、jQuery等のフレームワークは使わずに書いています。

category_select.js
// 取得したテキストをhtmlに変換する関数
var stringToHTML = function(str) {
    var dom = document.createElement('div');
    dom.id = 'sub_category';
    dom.innerHTML = str;
    return dom;
};

document.addEventListener('turbo:load', function() {
    let category = document.querySelector('#category');
    let defaultSubCategorySelect = `<select name="sub_category" id="sub_category">
    <option value>---</option>
    </select>`;

    // カテゴリーが変更された時の処理
    category.addEventListener('change', function() {
        
        // カテゴリーが選ばれた場合
        if (category.value !== '') {

            // 空のサブカテゴリーのセレクトボックスを削除
            let subCategory = document.querySelector('#sub_category');
            subCategory.remove();

            // 選択されたカテゴリーに応じたHTMLを挿入
            let selectedTemplate = document.querySelector(`#sub-category-of-category${category.value}`);
            category.after(stringToHTML(selectedTemplate.innerHTML));
        
        // include_blankの部分が選択された場合
        } else {

            // サブカテゴリー選択用のセレクトボックスを削除
            let subCategory = document.querySelector('#sub_category');
            subCategory.remove();

            // ダミーのセレクトボックスを挿入
            category.after(stringToHTML(defaultSubCategorySelect));
        };
    });
});

これで動的なセレクトボックスが作成できました。 

参考 

間違いやご指摘等あればコメントいただけると幸いです。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?