仅显示所选类别的子类别

时间:2015-04-23 18:15:59

标签: ruby-on-rails ruby model-view-controller

这是我目前的代码:

<%= f.collection_select :category_id, Category.all, :id, :name, {prompt: "Choose a category"} %>
<%= f.collection_select :subcategory_id, Subcategory.all, :id, :name, {prompt: "Choose a subcategory"} %>

所有这一切都是在一个下拉列表中显示所有类别,在另一个所有子类别中显示。 像这样the drop downs.

  

问题:如何根据所选的主要类别显示特定的子类别。使用上面的代码,它显示了所有类别和所有子类别。

模型中的所有东西都是链接的,has_many和belongs_to ...以及category_id和subcategory_id..everything正常工作,我只是不知道如何在所选类别中显示特定的子类别。

我的尝试:

  <% if (Category.where(:name=>"Intro")) do |d| %>
    <% d.subcategories.each do |subcategory| %>
      <%= link_to subcategory.name, gigs_path(subcategory: subcategory.name) %>
    <% end %>
  <% end %>

此代码出错。我要说,例如,如果用户选择名为“简介”的类别而不是列出所有“简介子类别”。但它没有成功 - 我的代码显然是错误的。

谢谢。

4 个答案:

答案 0 :(得分:8)

我假设您希望在不重新加载页面的情况下实现此目的?那时你不会想到一些JavaScript。这是一般工作流程:

  • 更改类别下拉列表时,发送一个Ajax请求,该请求将使用JavaScript进行响应并将正确的值插入子类别下拉列表中。

为了这个例子,我将假设您的表单(属于某个类别的模型)是一个帖子。你似乎没有提到这个模型。

让我们试试这个:

<强>视图/帖/ _form
我将在subcategories_select div中包装subategories selct框,这使我们可以在以后替换整个内容。

<%= f.collection_select :category_id, Category.all, :id, :name, { prompt: "Choose a category" }, id: "category_id" %>

<div id="subcategories_select">
 <%= f.collection_select :subcategory_id, Subcategory.all, :id, :name, { prompt: "Choose a subcategory" }, { disabled: true } %>
</div>

<强>资产/ Javascript角/ posts.js.erb

# select the element to watch for changes
$('form').on('change', '#category_id'), function() {
  var category_id = $(this).val(); # save the category_id set in the first dropdown

  $.ajax({
    url: "/categories/" + category_id + "/get_subcategories", # a custom route, see routes.rb further down
    type: "GET",
    dataType: "script", # we expect a response in js format
    data: { "category_id": category_id } # the only value we will need to get the subcategories
  });
});

<强>配置/ routes.rb中

# we need a custom route for our get_subcategories action
resources :categories do
  member do
    get :get_subcategories, defaults: { format: "js" }
  end
end

<强>控制器/ posts_controller.rb
重要提示:我假设类别has_many子类别和子类别具有category_id,这意味着属于一个类别。如果不是,那么下面的内容就没有意义。

# our custom controller action
def get_subcategories
  @subcategories = Subcategory.where(category_id: params[:category_id])
end

应用/视图/帖/ get_subcategories.js.erb
在这里,我们将替换subsategories_select div的内容,并使用适当的选项插入collection_select。

$('#subcategories_select').html("<%= j collection_select(:post, :category_id, @subcategories, :id, :title), { prompt: 'Select subcategory...' }, { disabled: false } %>");

请注意,我是从头脑中做到这一点,因此可能存在错误,但这是一种动态填充选择框的方法,或者通常在不重新加载的情况下更改页面上的任何内容。

答案 1 :(得分:1)

这就解决了我的问题

在javascript文件夹中(必须安装砌体gem)

$ ->
  $('#gigs').imagesLoaded ->
    $('#gigs').masonry
      itemSelector: '.box'
      isFitWidth: true

  $(document).on 'change', '#gig_category_id', (evt) ->
    $.ajax 'update_sub_categories',
      type: 'GET'
      dataType: 'script'
      data: {
        category_id: $("#gig_category_id option:selected").val()
      }
      error: (jqXHR, textStatus, errorThrown) ->
        console.log("AJAX Error: #{textStatus}")
      success: (data, textStatus, jqXHR) ->
        console.log("Dynamic country select OK!")
在Gig控制器中

respond_to :html, :js, :json
  def update_sub_categories
    @cats = Subcategory.where(category_id: params[:category_id]).all
    respond_with(@cats)
  end

我创建了一个部分的演出视图 _subcategory.html.erb 并把这段代码

<option value="<%= cat.id %>"><%= cat.name %></option>

比名为_update.html.erb的演出视图中的另一部分 把这段代码

$("#gig_subcategory_id").empty().append("<%= escape_javascript(render(:partial => "subcategory", :collection => @cats, :as => :cat)) %>")

最后在视图中显示类别和子类别,我使用了

  <%= f.collection_select :category_id, Category.all, :id, :name, {prompt: "Choose a category"} %>
  <%= f.collection_select :subcategory_id, Subcategory.all, :id, :name, {prompt: "Choose a subcategory"} %>

答案 2 :(得分:1)

使用js过滤collection_select可能非常困难。我建议使用group_collection_select,如果关系正确,则会过滤数据。 Asumming你有一个类似上面答案中提到的数据模型,视图应该是这样的:

的观点/帖/ _form:

<%= f.collection_select(:category_id, Category.all, :id, :name,    
               { prompt: 'Select a category' }, { id: 'category-select' }) %>

<%= f.grouped_collection_select :subcategory_id, Category.all, :subcategories, 
          :name, :id, :name, { include_blank: 'Select a sub category' },
                                               { id: 'subcategory-select' } %>

现在,您将能够看到两个选择表单,但groups_collection_select框显示了一些嵌套选项。为了只显示必要的子类别,我们需要在javascript中做一些更改,在我的情况下,使用咖啡,我的文件将被命名为.coffee而不是.js.erb

的应用程序/资产/ Javascript角/ posts.coffee:

jQuery ->
  subcat = $('#subcategory-select').html()
  $('#category-select').change ->
    cat = jQuery('#category-select').children('option').filter(':selected').text()
    options = $(subcat).filter("optgroup[label='#{cat}']").html()
    if options
      $('#subcategory-select').html(options)
    else
      $('#subcategory-select').empty()

我欠我对source的答案,您可以在其中找到有关使用group_collection_select的更多详细信息

答案 3 :(得分:0)

因此,您编写的嵌入式ruby在被发送到“客户端”之前会被评估。这意味着您编写的代码将变为静态HTML并发送给用户。

您想要的是使用能够在用户浏览器上提供逻辑操作的内容。这意味着javascript。

结帐:AngularJS:https://angularjs.org/