Javascript 如何使用祖先宝石在Rails中使用类别/子类别填充下拉列表(2个或更多深度级别)

Javascript 如何使用祖先宝石在Rails中使用类别/子类别填充下拉列表(2个或更多深度级别),javascript,ruby-on-rails,ruby,ajax,drop-down-menu,Javascript,Ruby On Rails,Ruby,Ajax,Drop Down Menu,我有Rails 5.2.3,我使用祖先宝石 我希望用户为汽车零件创建报价,但在新表单中,我希望能够选择零件所属的类别/子类别,然后填写我拥有的其他详细信息,然后提交表单以创建报价。假设有人想卖刹车片 所以首先必须选择类别/子类别等等 (因此,当他选择汽车时,第二个下拉列表应显示汽车的子类别) 例如: 下拉列表1:汽车下拉列表2:制动器 因此,在选择刹车后,他可以填写其他字段并提交 我所拥有的: 我已经在控制台中创建了Category/Subcategory,只是为了让它正常工作: 乙二醇 问题是

我有Rails 5.2.3,我使用祖先宝石

我希望用户为汽车零件创建报价,但在新表单中,我希望能够选择零件所属的类别/子类别,然后填写我拥有的其他详细信息,然后提交表单以创建报价。假设有人想卖刹车片

所以首先必须选择类别/子类别等等

(因此,当他选择汽车时,第二个下拉列表应显示汽车的子类别)

例如:

下拉列表1:汽车
下拉列表2:制动器

因此,在选择刹车后,他可以填写其他字段并提交

我所拥有的:

我已经在控制台中创建了Category/Subcategory,只是为了让它正常工作: 乙二醇

问题是下拉列表1有类别“Car”,下拉列表2总是空的,并且ofc我没有错误(我使用的是祖先,因为稍后我将添加许多类别/子类别/子类别等)


问题是:

也许您可以只使用一个选择框而不是两个选择框,但是使用?这可能更容易-并不是说你不能解决你当前的问题。@taylorthurlow我按照你说的做了,它工作得很好,但我想要单独的下拉列表的原因是我想扩展应用程序,我将有许多类别子类别,因此,如果只使用一个,那么当您循环数据时,javascript日志是否能够成功地发送到控制台<代码>控制台日志(id)明白了。所以那可能是开始寻找的最好地方。如果您还不知道如何在javascript中使用调试器。我将使用调试器检查
数据
成功
回调中的值。数据应该表示由
CategoriesController#select_item
操作作为JSON发送的类别项目列表。没有控制台日志这一事实意味着
数据.forEach
实际上没有在任何数据上循环。也许可以使用一个选择框而不是两个选择框,但是使用?这可能更容易-并不是说你不能解决你当前的问题。@taylorthurlow我按照你说的做了,它工作得很好,但我想要单独的下拉列表的原因是我想扩展应用程序,我将有许多类别子类别,因此,如果只使用一个,那么当您循环数据时,javascript日志是否能够成功地发送到控制台<代码>控制台日志(id)明白了。所以那可能是开始寻找的最好地方。如果您还不知道如何在javascript中使用调试器。我将使用调试器检查
数据
成功
回调中的值。数据应该表示由
CategoriesController#select_item
操作作为JSON发送的类别项目列表。没有控制台日志这一事实意味着
data.forEach
实际上没有在任何数据上循环。
car = Category.create!(name: "Car")
brakes = Category.create!(name: "Brakes", parent: car)
#category.rb
class Category < ApplicationRecord
  has_ancestry cache_depth: true
  has_many :parts
end
#part.rb
class Part < ApplicationRecord
  belongs_to :category
end
#categories_controller.rb
class CategoriesController < ApplicationController
  def select_item
    category = @category.find(params[:category_id])
    render json: category.children
  end
end
#app/inputs/fake_select_input.rb
class FakeSelectInput < SimpleForm::Inputs::CollectionSelectInput
  def input(wrapper_options = nil)
    label_method, value_method = detect_collection_methods

    merged_input_options = 
    merge_wrapper_options(input_html_options, 
    wrapper_options).merge(input_options.slice(:multiple, 
    :include_blank, :disabled, :prompt))

    template.select_tag(
      attribute_name,
      template.options_from_collection_for_select(collection, 
      value_method, label_method, selected: 
      input_options[:selected], disabled: 
      input_options[:disabled]),
      merged_input_options
    )
  end
end
#routes.rb 
 Rails.application.routes.draw do
  resources :parts
  resources :categories, only: [] do
   get :select_item, on: :collection
  end
 end
#application.js
  $('#first-dropdown').on('change', function() {
    $.ajax({
    url: 'categories/select_item?category_id=' + $(this).val(),
    dataType: 'json',
    success: function(data) {
      var childElement = $('#second-dropdown');
      childElement.html('');
      data.forEach(function(v) {
        var id = v.id;
        console.log(id);
        var name = v.name;
        childElement.append('<option value="' + id + '">' + name + '</option>');
      });
     }
   });
 });
#views/parts/new.html.haml
  = simple_form_for @part do |f|
    = f.input :parent_category_id, as: :fake_select, collection: Category.roots, input_html: { id: 'first-dropdown' }, label: "Category"
    = f.input :category_id, collection: [], input_html: { id: 'second-dropdown' }, label: "Subcategory"
    = f.input :title
    = f.input :part_number
    = f.input :price, label: "Price"
    = f.input :condition, label: "Condition", prompt: "-", collection:([["New", "New"], ["Used", "Used"], ["Rebuilt", "Rebuilt"], ["Aftermarket/Imitation", "Aftermarket/Imitation"]])
    = f.input :make, label: "Part Make"
    = f.input :part_model_name, label: "Part Model"
    = f.input :description
    .form-group
      = f.button :submit, class: "btn btn-primary btn-block"