Rails:根据下拉列表中的选定值更改索引

时间:2017-02-25 14:19:28

标签: ruby-on-rails ruby drop-down-menu simple-form

我有两种模式:

class Location < ActiveRecord::Base
    has_many :cows
    accepts_nested_attributes_for :cows
end

class Cow < ActiveRecord::Base
    belongs_to :location
end

每个位置都有一个id,一个名称和三个布尔值。一头奶牛由一个id,两个字符串和两个日期组成,它还包含一个location_id。

在我的牛视图中,我有一个每个位置的下拉列表。每当我创建,编辑或删除位置时,它都会自动更新。 enter image description here

在下拉列表下方,您可以看到所有已创建的奶牛。有一个表单可以添加一个带有两个字符串字段和两个日期字段的新牛。 enter image description here

现在我想要两件事:每当我在下拉列表中选择一个值时,显示的奶牛应该会改变。如果我选择例如位置2,则只应显示表中具有location_id = 2的奶牛。此外,当我创建一个新的母牛时,也应保存所选位置的id(在此示例中,当我点击最底部的按钮时,location_id = 2应该保存在母牛行中。)

这是牛index.html文件中动态下拉列表的样子:

  <%= simple_form_for Cow.new do |f| %>
    <%= f.collection_select :location, Location.order('name').all, :id, :name, { prompt: "Ort auswählen" } %>
  <% end %>

这是我的奶牛控制员:

  def index
    if (params[:location] && Location.all.collect(&:name).include?(params[:location][:name]))
     @cows = Cow.send(params[:location][:name].downcase)
    else
     @cows = Cow.all
    end
  end

  # (...)

  def create
    @cow = Cow.new(cow_params)
    # (...)
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_cow
      @cow = Cow.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def cow_params
      params.require(:cow).permit(:ohrmarke, :hin, :weg, :stallnummer, :location_attributes => [:id])
    end
end

编辑后的索引部分不起作用。也许是因为我有一个关于Cow.new的下拉菜单而且我没有提交按钮。现在问题是:我需要新牛的下拉(值),但也想显示适合所选下拉值的奶牛。此外,我不想仅为下拉框使用提交按钮。我的问题有什么解决方案吗?我用Google搜索了这么多,但却无法找到解决问题的正确答案。

修改 我编辑了我的奶牛控制器和我的索引页面: 牛控制器:

def index
    @locations_all = Location.all
    if (params[:location] && cows = Cow.where(location_id: params[:location]))
      @cows = cows
      @location = Location.where(id: params[:location])
    else
      @cows = Cow.all
    end
end

# (...)

def create
  @cow = Cow.new(cow_params)
  # (...)
end

private
  # Use callbacks to share common setup or constraints between actions.
  def set_cow
    @cow = Cow.find(params[:id])
  end

  # Never trust parameters from the scary internet, only allow the white list through.
  def cow_params
    params.require(:cow).permit(:ohrmarke, :hin, :weg, :stallnummer, :location_attributes => [:id])
  end

牛index.html:

  <%= simple_form_for Cow.new do |f| %>
    <%= f.collection_select :location, Location.order('name').all, :id, :name, { prompt: "Ort auswählen" } %>
    <ul>
      <% @locations_all.each do |loc| %>
        <li><%= link_to loc.name, @cows.index(location: loc.id) %></li>
      <% end %>
    </ul>


    <%= f.hidden_field :location_id, value: @location_id %>

    <table class="striped">
      <thead class="thead-default">
        <tr>
          <th>Ohrmarke</th>
          <th>Stallnr.</th>
          <th>Hin/Weg</th>
        </tr>
      </thead>
      <tbody>
        <!-- ... -->
      </tbody>
    </table><br>

    <%= f.input :ohrmarke, as: :string, input_html: { maxlength: 5 } %>
    <%= f.input :stallnummer, as: :string, input_html: { maxlength: 3 } %>

    <!-- datepicker not functional yet -->
    <input type="date" class="datepicker" id="hin" placeholder="hin">
    <input type="date" class="datepicker" id="hin" placeholder="weg">

    <button class="btn waves-effect waves-light" type="submit" name="action">Zuordnung speichern
      <i class="material-icons right">send</i>
    </button>
  <% end %>

1 个答案:

答案 0 :(得分:1)

下拉&amp;内容

这是cows_controller#index的可能实现。

def index
    @locations_all = Location.all
    if (params[:location] && cows = Cow.where(location_id: params[:location]))
      @cows = cows
      @location = Location.where(id: params[:location])
    else
      @cows = Cow.all
    end
end

然而,有一些重要的要点和一些问题。 您用于下拉列表的代码假定您正在发出POST请求,在这种情况下不需要。使用简单的link_to可以实现同样的目的。为了实现这一点,你会有类似的东西:

<ul>
    <% @locations_all.each do |loc| %>
        <li><%= link_to loc.name, cows_path(location: loc.id) %></li>
    <% end %>
</ul>

<强>表格

为了让表单使用正确的位置创建新的Cow,您需要在其中加入hidden_field

<%= f.hidden_field :location_id, value: @location.id %>

但这引入了一个设计问题。如果您未在下拉菜单中选择任何location,会发生什么?有很多方法可以解决这个问题,但我最喜欢的解决方案是在这种情况下隐藏表单。

<% unless @location %>
    #form-block ...
<% end %>

如果在没有指定cows的情况下无法创建location,此解决方案似乎很理想。

修改

好的,现在我可以看到HTML了。我可以告诉你什么是错的。您的simple_form_for区块围绕着整个视图。这可能不是你想要的。 forms通常是POST请求,因此您只需要在计划发送数据或在表上创建新条目时使用这些请求。 link_to是一个GET请求,您可以向服务器请求信息。这是我的观点的一个小例子:

#drop-down menu
<div id="cow_menu">
    <ul>
        <% @locations_all.each do |loc| %>
            <li><%= link_to loc.name, cows_path(location: loc.id) %></li>
        <% end %>
    </ul>
</div>

#table
<table class="striped">
    # your table logic...  
</table>

#new Cow form
<%= simple_form_for Cow.new do |f| %>
    <%= f.hidden_field :location_id, value: @location_id %>
    <%= f.input :ohrmarke, as: :string, input_html: { maxlength: 5 } %>
    <%= f.input :stallnummer, as: :string, input_html: { maxlength: 3 } %>
    <%= f.submit "Zuordnung speichern", class="btn waves-effect waves-light"%>
<% end %>