Filter field based on previous field selection

橙三吉。 提交于 2019-12-08 12:03:30

问题


How can I use simple_form to filter a field, based on a previous fields value?

For instance, I have an Opportunities form, with two fields, Company and Contact.

Company Field:

  <div class="form-group">
    <%= f.association :company, collection: Company.all.order(:account), prompt: "", :label_method => :account, :value_method => :id %>
  </div>

Contact Field:

  <div class="form-group">
    <%= f.association :contact, collection: Contact.all.order(:first_name), prompt: "", :label_method => lambda { |contact| "#{contact.first_name} #{contact.last_name}" }, :value_method => :id %>
  </div>

Here is what I want to do: If I select a company called "Deviant" from the Company field above, I want the Contact field to only display those contacts associated with the company called "Deviant".

I am trying something like this, but can't get it to work:

  <div class="form-group">
    <%= f.association :contact, collection: Contact.where("company_id = ?", params[:id]), prompt: "", :label_method => lambda { |contact| "#{contact.first_name} #{contact.last_name}" }, :value_method => :id %>
  </div>

I don't know how to reference the value in the Company field.

How can I do this?

Thanks.

Update

Anyone? Surely this must be possible. This is a key functionality in any form. I would hope I don't need jQuery or something.


回答1:


I think the best approach is to use ajax requests to update your contacts collection dinamically whenever the company's selected value is changed.

First you'll need an action in your contacts controller:

app/controllers/contacts_controller.rb

class ContactsController < ApplicationController
  def contacts_list
    if params[:company_id]
      @contacts = Contact.where(company_id: params[:company_id])
    else
      @contacts = Contact.all
    end

    respond_with(@contacts) do |format|
      format.json { render :json => @contacts.to_json(:only => [:id, :first_name, :last_name]) }
    end        
  end
end

Add this to your routes:

config/routes.rb

  post 'contacts_list' => "contacts#contacts_list", as: :contacts_list

Then use the coffeescript code bellow to populate your contacts' collection:

app/assets/javasctipts/companies.js.coffee

$(document).ready ->
  if $("#opportunity_company_id")
    populate_contacts()
    $("#opportunity_company_id").change ->
      populate_contacts()

populate_contacts = ->
  $contacts_select = $("select#opportunity_contact_id")
  $contacts_select.attr "disabled", "disabled"
  company_id = $("select#opportunity_company_id").val()
  if company_id is ""
    $contacts_select.html "<option value=\"\">(select the company first)</option>"
  else
    $contacts_select.html "<option value=\"\">(loading contacts...)</option>"
    data = {company_id: company_id}
    data[window._auth_token_name] = window._auth_token
    $.ajax "/contacts_list",
      type: "post"
      dataType: "json"
      data: data
      success: (contacts) ->
        _html = '<option value="">Select the contact:</option>'
        _html += '<option value="'+contact.id+'">'+contact.first_name + ' ' + contact.last_name + '</option>' for contact in contacts
        $contacts_select.html _html
        $contacts_select.removeAttr "disabled"
      error: ->
        alert 'Error trying to load contacts.'

Finally, inside your html's head tag:

<% if protect_against_forgery? %>
  <script>
    window._auth_token_name = "<%= request_forgery_protection_token %>";
    window._auth_token = "<%= form_authenticity_token %>";
  </script>
<% end %>

Hope it helps...

update: Add the following line to your ApplicationController (app/controllers/application_controller.rb):

respond_to :html, :xml, :json, :js


来源:https://stackoverflow.com/questions/20180903/filter-field-based-on-previous-field-selection

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!