Rails:通过下拉列表和复选框过滤索引

发布于 2024-12-06 02:33:31 字数 3617 浏览 0 评论 0原文

我试图通过下拉菜单(位置)和一组复选框(类别)来过滤产品的索引页,但效果不是很成功。我可以通过下拉菜单过滤位置或类别。我还可以将两个下拉菜单合并到一个表单中,但如果我无法为两个单独的表单提供有效的解决方案。

我想要实现的是提交 onchange 的位置的下拉菜单以及我想要作为带有过滤器按钮的复选框的类别。

我目前的代码提供了下拉列表和复选框,但存在一些问题:

  • 视图中都不会返回任何产品
  • 复选框列出了所有类别,但是当我根据这些类别进行过滤时,参数将作为数组传递,但每当我过滤时, 类别我丢失了以前的位置选择

这是相关的代码:

产品模型

....
has_many :categorizations
has_many :categories, :through => :categorizations
has_many :localizations
has_many :locations, :through => :localizations
class Product < ActiveRecord::Base
default_scope :order => 'end_date'
scope :not_expired, where('end_date > ?', Time.now)
scope :location, lambda { |*location_id| {:include => :locations, :conditions => ["locations.id = ?", location_id]} }
scope :category, lambda { |*category_id| {:include => :categories, :conditions => ["categories.id = ?", category_id]} }
scope :unique, :group => "title"

控制器

class LibraryController < ApplicationController
  def index
    if params[:location_id] && params[:category_ids]
    @products = Product.not_expired.unique.location(params[:location_id]).category(params[:category_ids]).paginate(:page => params[:page], :per_page => 9)
    elsif params[:category_ids]
    @products = Product.not_expired.unique.category(params[:category_ids]).paginate(:page => params[:page], :per_page => 9)
    elsif params[:location_id]
    @products = Product.not_expired.unique.location(params[:location_id]).paginate(:page => params[:page], :per_page => 9)
    else
    @products = Product.not_expired.unique.paginate(:page => params[:page], :per_page => 9)
    end
  end
end

库index.html.erb

<% if notice %>
<p id="notice"><%= notice %></p>
<% end %>

      <div class="filter_options">

        <form class="filter_locations", method="get">
          <% @options = Location.all.map { |a| [ a.name, a.id ] } %>
          <%= select_tag "location_id", options_for_select(@options), :onchange => "this.form.submit();", :include_blank => true %> 
        </form>

        <form class="filter_categories", method="get">
          <% for category in Category.all %>
            <%= check_box_tag("[category_ids][]", category.id) %>
            <%= category.name %>
          <% end %>
          <input type="submit" value="Filter" />
        </form>
    </div>

我一直在绕圈子,所以任何方向都非常感激。

为了部分回答我自己的问题,我修改了库索引,并在类别表单中使用了一个隐藏字段,该字段调用 location_id 参数(如果存在),这意味着我可以保留在选择类别复选框后所做的任何位置选择。

进一步更新是我添加了一个检查,检查是否通过查询参数来检查类别复选框,更新了下面的库index.html.erb。

最后编辑@rdvdijk输入并入(谢谢)

库index.html.erb

.......
    <%= form_tag( '', :method => :get ) do %>
      <% @options = Location.all.map { |a| [ a.name, a.id ] } %>
      <%= select_tag "location_id", options_for_select((@options), params[:location_id]), :onchange => "this.form.submit();", :include_blank => true %> 
    <% end %>
    <%= form_tag( '', :method => :get ) do %>
      <% if(params.has_key?(:location_id)) %>
        <%= hidden_field_tag 'location_id', params[:location_id] %> 
      <% end %>
    <% Category.all.each do |category| %>
    <%= check_box_tag 'category_ids[]', category.id, params[:category_ids].to_s.include?(category.id_to_s) %>
      <%= category.name %>
    <% end %>
    <%= submit_tag 'Filter' %>
    <% end %>
.......

I'm trying to filter an index page of products via a dropdown menu (locations) and a set of checkboxes (categories) and not being very successful with it. I can filter via a dropdown for either location or category. I can also combine the two dropdowns within the one form but if I can't get a working solution to two separate forms.

What i'd like to achieve is a dropdown for location that submits onchange and the categories I'd like to have as checkboxes with a filter button.

The code I have at the moment provides the dropdown and checkboxes but there are some problems:

  • the checkboxes list all the categories but when I filter based on these the params are passed as an array but no products are returned in the view
  • whenever I filter by category i lose the previous location selection

Here's the relevant code:

Product Model

....
has_many :categorizations
has_many :categories, :through => :categorizations
has_many :localizations
has_many :locations, :through => :localizations
class Product < ActiveRecord::Base
default_scope :order => 'end_date'
scope :not_expired, where('end_date > ?', Time.now)
scope :location, lambda { |*location_id| {:include => :locations, :conditions => ["locations.id = ?", location_id]} }
scope :category, lambda { |*category_id| {:include => :categories, :conditions => ["categories.id = ?", category_id]} }
scope :unique, :group => "title"

Controller

class LibraryController < ApplicationController
  def index
    if params[:location_id] && params[:category_ids]
    @products = Product.not_expired.unique.location(params[:location_id]).category(params[:category_ids]).paginate(:page => params[:page], :per_page => 9)
    elsif params[:category_ids]
    @products = Product.not_expired.unique.category(params[:category_ids]).paginate(:page => params[:page], :per_page => 9)
    elsif params[:location_id]
    @products = Product.not_expired.unique.location(params[:location_id]).paginate(:page => params[:page], :per_page => 9)
    else
    @products = Product.not_expired.unique.paginate(:page => params[:page], :per_page => 9)
    end
  end
end

Library index.html.erb

<% if notice %>
<p id="notice"><%= notice %></p>
<% end %>

      <div class="filter_options">

        <form class="filter_locations", method="get">
          <% @options = Location.all.map { |a| [ a.name, a.id ] } %>
          <%= select_tag "location_id", options_for_select(@options), :onchange => "this.form.submit();", :include_blank => true %> 
        </form>

        <form class="filter_categories", method="get">
          <% for category in Category.all %>
            <%= check_box_tag("[category_ids][]", category.id) %>
            <%= category.name %>
          <% end %>
          <input type="submit" value="Filter" />
        </form>
    </div>

I've been going around in circles with this so any direction is greatly appreciated.

to part answer my own question I've modified the library index and used a hidden field in the category form that calls for the location_id param, if it exists, which means I can retain any location selection that's been made after selecting category checkboxes.

Further update is I've added a check for whether the category checkbox is checked by querying the params, updated library index.html.erb below.

Last edit with @rdvdijk input incorporated (Thanks)

library index.html.erb

.......
    <%= form_tag( '', :method => :get ) do %>
      <% @options = Location.all.map { |a| [ a.name, a.id ] } %>
      <%= select_tag "location_id", options_for_select((@options), params[:location_id]), :onchange => "this.form.submit();", :include_blank => true %> 
    <% end %>
    <%= form_tag( '', :method => :get ) do %>
      <% if(params.has_key?(:location_id)) %>
        <%= hidden_field_tag 'location_id', params[:location_id] %> 
      <% end %>
    <% Category.all.each do |category| %>
    <%= check_box_tag 'category_ids[]', category.id, params[:category_ids].to_s.include?(category.id_to_s) %>
      <%= category.name %>
    <% end %>
    <%= submit_tag 'Filter' %>
    <% end %>
.......

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

時窥 2024-12-13 02:33:31

你有两种形式,我认为这是你问题的一部分。每当您在第一个表单中更改位置时,只有 location_id 才会发送到您的控制器 index 操作。每当您选择一个类别并提交第二个表单时,只有 category_ids 将发送到您的控制器 index 操作。

使用一个表单看看会发生什么。它至少应该使过滤适用于单个提交。

我看到的第二个问题是您没有选择所选位置,或检查所选类别。

查看 options_for_selectcheck_box_tag 来解决这个问题。

You have two forms, I think that is part of your problem. Whenever you change a location in the first form, only the location_id will be sent to your controller index action. Whenever your select a category and submit the second form, only the category_ids will be sent to your controller index action.

Use one form and see what happens. It should at least make the filtering work for a single submit.

The second problem I see is that you don't select the chosen location, or check the chosen categories.

Take a look at the documentation for options_for_select and check_box_tag to fix that.

残月升风 2024-12-13 02:33:31

就我而言,产品belongs_to:category和类别has_many:products,我将categories.id修改为category_id,它有效!

scope :category, lambda { |*category_id| {:include => :categories, :conditions => ["category_id = ?", category_id]} }

In my case, product belongs_to :category and category has_many :products, I modified categories.id to category_id, it works!

scope :category, lambda { |*category_id| {:include => :categories, :conditions => ["category_id = ?", category_id]} }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文