Schienen: Ändern Sie den Index basierend auf dem ausgewählten Wert im Dropdown-Menü


GoYoshi

Ich habe zwei Modelle:

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

class Cow < ActiveRecord::Base
    belongs_to :location
end

Jeder Standort hat eine ID, einen Namen und drei boolesche Werte. Eine Kuh besteht aus einer ID, zwei Strings und zwei Daten und enthält auch eine location_id.

In meiner Kuhansicht habe ich eine Dropdown-Liste mit jedem Standort. Es wird automatisch aktualisiert, wenn ich einen Standort erstelle, bearbeite oder lösche.Geben Sie hier die Bildbeschreibung ein

Unter dem Dropdown sehen Sie alle jemals angelegten Kühe. Danach gibt es ein Formular zum Hinzufügen einer neuen Kuh mit den beiden Stringfeldern und zwei Datumsfeldern.Geben Sie hier die Bildbeschreibung ein

Now I want two things: Whenever I select a value in the dropdown, the displayed cows should change. If I select for example location 2, only cows that have a location_id = 2 in the table should be shown. Also when I create a new cow, the id of the selected location should be saved as well (in this example location_id = 2 should be saved in the cow row when I click the button at the very bottom).

This is how the dynamic dropdown looks like in the cow index.html file:

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

And this is my cow controller:

  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

The edited index part just does not work. Perhaps because I have a dropdown for Cow.new and I don't have a submit button. Now the thing is: I need the dropdown (value) for a new cow but also want to display cows that fit to the selected dropdown value. Also I don't want to use a submit button just for the dropdown box. Is there any solution for my problem? I googled so much but just can't find the right answer for my problem.


Edit: I edited my cows controller and my index page: cow controller:

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

cow 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 %>
ScieCode

Drop-down & Content

This is a possible implementation for 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

There are however a few important points to be made and a few problems. The code you're using for the drop-down assumes you're making a POST request which isn't necessary in this case. The same can be achieved with a simple link_to. In order for this to work, you'd have something similar to this:

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

Form

In order for the form to create a new Cow using the correct location you'd need to include a hidden_field inside it.

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

But this introduces a design problem. What happens when you haven't selected any location on the drop-down menu? There are plenty of ways to handle this problem, but my favorite solution is to hide the form in that case.

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

This solutions seems ideal if cows can't be created without a specified location.


Edit

Ok, jetzt kann ich Sie HTML sehen. Ich kann Ihnen sagen, was falsch ist. Ihr simple_form_forBlock umgibt die gesamte Ansicht. Was Sie wahrscheinlich nicht wollen. formssind in der Regel POST-Anfragen, die Sie also nur benötigen, wenn Sie Daten senden oder einen neuen Eintrag in einer Tabelle erstellen möchten. link_toist eine GET-Anfrage, mit der Sie Informationen an den Server anfordern können. Dies ist ein kleines Beispiel dafür, wie meine Ansicht aussehen würde:

#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 %>

Verwandte Artikel