You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Active Admin自关联分类父子下拉框联动实现咨询

实现Active Admin中分类自关联的级联下拉效果

当然可以实现这个级联下拉的效果!我在多个Rails项目里都用过类似的方案,下面是具体的实现步骤,一步步来就行:

1. 先确保分类Model的自关联配置正确

首先检查你的Category模型,确保自关联关系已经正确设置,这样后续才能正确获取父分类对应的子分类:

# app/models/category.rb
class Category < ApplicationRecord
  # 关联父分类,允许为空(顶级分类没有父分类)
  belongs_to :parent, class_name: "Category", optional: true
  # 关联子分类,父分类被删除时子分类也一起删除
  has_many :children, class_name: "Category", foreign_key: "parent_id", dependent: :destroy

  # 可选:添加scope快速筛选顶级分类
  scope :top_level, -> { where(parent_id: nil) }
end

2. 在Active Admin资源文件中自定义表单并添加AJAX接口

接下来在app/admin/category.rb里,我们需要自定义表单结构,同时新增一个接口用于AJAX获取子分类数据:

# app/admin/category.rb
ActiveAdmin.register Category do
  # 记得把需要的属性加入permit_params
  permit_params :name, :parent_id, :description # 替换成你的实际属性

  form do |f|
    f.inputs "分类信息" do
      f.input :name
      # 父分类下拉框:只显示顶级分类,添加ID方便JS定位
      f.input :parent, 
              collection: Category.top_level, 
              include_blank: "选择父分类",
              input_html: { id: "category_parent_id" }
      # 子分类下拉框:编辑页面时自动加载对应父分类的子分类,新增页面先清空
      f.input :children, 
              as: :select,
              collection: f.object.parent.present? ? f.object.parent.children : [],
              include_blank: "选择子分类",
              input_html: { id: "category_children" }
    end
    f.actions
  end

  # 新增controller action,处理AJAX请求返回子分类的JSON数据
  controller do
    def get_children
      parent_category = Category.find(params[:parent_id])
      # 提取子分类的名称和ID,用于生成下拉选项
      children_data = parent_category.children.pluck(:name, :id)
      render json: children_data
    end
  end

  # 注册member路由,让AJAX能访问到上面的action
  member_action :get_children, method: :get
end

3. 添加JavaScript实现级联逻辑

最后我们需要写一段JS来监听父分类下拉框的变化,动态更新子分类选项。你可以把这段代码放在app/assets/javascripts/active_admin/categories.js(没有目录的话自行创建):

// app/assets/javascripts/active_admin/categories.js
document.addEventListener('turbo:load', function() {
  const parentSelect = document.getElementById('category_parent_id');
  const childSelect = document.getElementById('category_children');

  if (parentSelect && childSelect) {
    // 监听父分类下拉框的选择变化
    parentSelect.addEventListener('change', function() {
      const parentId = this.value;
      
      // 如果没选父分类,清空子分类选项
      if (!parentId) {
        childSelect.innerHTML = '<option value="">选择子分类</option>';
        return;
      }

      // 发送AJAX请求获取子分类数据
      fetch(`/admin/categories/${parentId}/get_children`)
        .then(response => response.json())
        .then(children => {
          // 清空现有选项
          childSelect.innerHTML = '<option value="">选择子分类</option>';
          // 逐个添加子分类选项
          children.forEach(child => {
            const option = document.createElement('option');
            option.value = child[1];
            option.textContent = child[0];
            childSelect.appendChild(option);
          });
        })
        .catch(error => console.error('加载子分类失败:', error));
    });
  }
});

额外注意点

  • 如果你的项目用了Rails 7+的Turbo,记得用turbo:load事件代替DOMContentLoaded,避免页面刷新后事件失效。
  • 编辑页面时,表单已经自动加载了对应父分类的子分类,不需要额外处理。
  • 确保Active Admin用户有权限访问get_children接口,默认member_action是允许的,如果有自定义权限规则需要调整。

内容的提问来源于stack exchange,提问作者Adwait soni

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 00:07:32