【问题标题】:Rails ancestry gem + Render and choose category/subcategory in new formRails 祖先 gem + 渲染并以新形式选择类别/子类别
【发布时间】:2018-12-20 22:56:07
【问题描述】:

我有 Rails 5.2.2,我正在尝试实现祖先 gem。

所以我想要什么:

我希望用户为汽车零件创建报价,但在新表单中,我希望能够选择类别/子类别,然后输入我拥有的其他详细信息,然后提交表单以创建提供。假设有人想添加销售刹车片。 但首先必须选择父类别。 例如

汽车->刹车->刹车片

所以在选择刹车片后,他可以创建报价。

我有什么:

#category.rb
class Category < ApplicationRecord
  has_ancestry
  has_many :parts
end

-

#part.rb
class Part < ApplicationRecord
  belongs_to :category
end

目前,我已经在控制台中创建了一个以使其工作: 例如

car = Category.create!(name: "Car")
brakes = Category.create!(name: "Brakes", parent: car)
brake_pads = Category.create!(name: "Brake Pads", parent: brakes)

我也已经运行了迁移rails g migration add_category_to_parts category:references

我的看法:

#views/parts/new.html.haml
.container
  %h2.center Create offer
  = simple_form_for(@part, html: {class: "form-group" }) do |f|
    .form-group.col-md-8.col-md-offset-2.well
      = f.input :title
      = f.input :make_name, label: "Make"
      = f.input :code, label: 'Part number'
      = f.association :condition, label_method: :name, prompt: "-"
      = f.input :description
      .form-actions
        = f.button :submit, class: "btn btn-primary btn-dark-blue"

问题是: 我如何在我的视图-> 部分-> new.html.haml 表单中呈现类别/子类别,其中包含 3 个下拉菜单(每个子类别一个,因为我将有很多类别/子类别),以便用户可以选择它们然后创建报价?

【问题讨论】:

  • 您不想创建类别控制器的原因是什么?虽然您可以通过种子或控制台手动设置类别,但类别应该被视为它自己的资源(在我看来)。
  • 嗨,马克,非常感谢您的回复。我想是因为一旦我不需要控制器来做其他事情,我就会创建类别,但我会创建一个。 (我编辑了我的问题:我想在 view->parts-> new.html.haml 中呈现类别/子类别)。如果我创建类别控制器,你知道如何在部分新表单中呈现这些吗?

标签: ruby-on-rails ruby ruby-on-rails-5 simple-form ancestry


【解决方案1】:

无论如何你都需要 CategoriesController,因为你需要依赖下拉菜单。当用户在第一个选择类别时,您需要发出AJAX请求以获取子类别等

# config/routes.rb
resources :categories, only: [] do
  get :select_item, on: :collection
end

# app/assets/javascripts/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;
        var name = v.name;
        childElement.append('<option value="' + id + '">' + name + '</option>');
      });
    }
  });
});

# app/controllers/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

# views/parts/new.html.haml
.form-group.col-md-8.col-md-offset-2.well
  = f.input :title
  = f.input :make_name, label: "Make"
  = f.input :code, label: 'Part number'
  = f.association :condition, label_method: :name, prompt: "-"
  = f.input :description
  = f.input :parent_category_id, as: :fake_select, collection: Category.roots, input_html: { id: 'first-dropdown' }
  = f.input category_id, collection: [], input_html: { id: 'second-dropdown' }
  .form-actions
    = f.button :submit, class: "btn btn-primary btn-dark-blue"

由于 simple_form 依赖于使用模型,您需要为非模型字段(父类别)创建自定义输入。您只需将一个 category_id 保存到@part,始终可以从中获取父类别。 如果您需要超过 2 个下拉菜单,只需添加一个功能或(更好)更改它,这样您就可以将依赖下拉菜单作为参数传递

【讨论】:

  • Vasilisa 非常感谢您的回答。现在的问题是第一个下拉列表包含所有类别/子类别,第二个下拉列表为空白
  • @Stefanos,第一次选择应该是Category.roots 而不是Category.all。第二个选择应该是空白的,直到您在第一个选择中做出选择,对吗?
  • Vasilisa(由于某种原因@name 不起作用),对于第一个元素,我将“Category.all”更改为Category.roots,正如您所说,它完美运行并且仅包含类别.对于第二个下拉列表,你是对的,它应该是空白的,直到我在第一个中选择类别,但现在第一个完全按照我想要的解决方案工作,第二个仍然是空白,即使我选择了一个类别第一个下拉菜单。 非常感谢您的宝贵时间和帮助,但我仍在学习 RoR,因为我非常喜欢它 ;)
  • @Stefanos,你有js调试技巧吗?如果来自服务器的$(this).val()data 正确,您需要检查console.log。您在select_item 操作中的服务器日志中有什么内容?
  • Vasilisa 我不懂 js,这就是我无法让它工作的原因,我可以通过单个下拉菜单让它完美地工作,但我想要像你的解决方案这样更好的东西。我打开控制台,在 js 代码中有一些错误,特别是在这一行 ('&lt;option value="' + id '"&gt;' + name + '&lt;/option&gt;');,但很抱歉我不知道 js。如果您在 js 验证器中复制代码,我认为您可能会立即解决它。它说的是语法错误
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-08
相关资源
最近更新 更多