如何使用select2-rails和simple_form?

时间:2021-12-19 15:57:44

This select2 jquery library looks awesome. There is a Rails gem but it is very light on the documentation. I would like to generate a simple multiple drop-down menu, using autocomplete. How do I do that?

这个select2 jquery库看起来很棒。有一个Rails gem,但是它对文档非常了解。我想使用autocomplete生成一个简单的多下拉菜单。我该怎么做呢?

This is my simple_form_for call:

这是我的simple_form_for调用:

<%= f.input_field :neighborhood_names, url: autocomplete_neighborhood_name_searches_path, as: :autocomplete, data: { delimiter: ',', placeholder: "Where do you want to live?"}, multiple: true, id: "selectWhereToLive", class: "span8" %>

I have successfully installed the select2-rails gem, but not quite sure how to get it working.

我已经成功地安装了select2-rails gem,但是不确定如何让它工作。

I add this to my home.js.coffeefile:

我把这个添加到家里。

jQuery ->
    $('#selectWhereToLive').select2()

And am getting this error:

我得到了这个错误:

Uncaught query function not defined for Select2 selectWhereToLive 

Thoughts?

想法吗?

Edit 1:

编辑1:

The above simple_form_for call is producing this HTML:

上面的simple_form_for调用生成这个HTML:

<input class="autocomplete optional span8" data-autocomplete="/searches/autocomplete_neighborhood_name" data-delimiter="," data-placeholder="Where do you want to live?" id="selectWhereToLive" multiple="multiple" name="search[neighborhood_names][]" size="30" type="text" url="/searches/autocomplete_neighborhood_name" value="" />

Indicating that the id attribute is being properly set.

指示id属性正在正确设置。

Edit 2 - Updated

编辑2 -更新

As @moonfly suggested, I tried adding as: :select to the f.input_field - both with as: :autocomplete included and not included.

正如@moonfly所建议的,我尝试添加As::select to the f。input_field -包含和不包含as::autocomplete。

The resulting HTML without as: :autocomplete was this:

没有as::autocomplete的结果是:

<input name="search[neighborhood_names][]" type="hidden" value="" /><select class="select optional span8" data-delimiter="," data-placeholder="Where do you want to live?" id="selectWhereToLive" multiple="multiple" name="search[neighborhood_names][]" url="/searches/autocomplete_neighborhood_name"><option value="true">Yes</option>
<option value="false">No</option></select>

It pre-populates 2 option values 'Yes' and 'No'. Not quite sure why, but that is what it does.

它预填充两个选项值“Yes”和“No”。不太清楚为什么,但这就是它的作用。

Update

更新

So I had changed the jquery selector to look for input#ID, and forgot. So I set that back and now it is generating the select box - but it is giving me those 2 Yes & No options. Not quite sure why it is doing that. It's not returning the values in from my url attribute.

因此,我更改了jquery选择器以查找输入#ID,并忘记了。我把它放回去,现在它生成了选择框,但它给了我2个Yes和No选项。不知道为什么会这样。它不会从我的url属性返回值。

Edit 3

编辑3

@harish-shetty's suggestion seems to be working. But now, after it has successfully found the records via autocomplete and using the select2 menu, it is bypassing the setter method I have on my search.rb model.

@harish-shetty的建议似乎奏效了。但是现在,在它通过自动完成和使用select2菜单成功找到记录之后,它绕过了我在搜索中的setter方法。rb模型。

Basically, what I want to happen is, once the user has finished filling out the form - and I have all the IDs/names for the neighborhoods they want, I want to create a new record in search_neighborhoods for those IDs.

基本上,我希望发生的是,一旦用户填写完表单——我有了他们想要的社区的所有id /名称,我想为这些id在search_communities中创建一个新记录。

So these are the methods I have:

这些就是我的方法

Search.rb

  def neighborhood_names
    neighborhoods.map(&:name).join(',')
  end

  # we need to put [0] because it returns an array with a single element containing
  # the string of comma separated neighborhoods
  def neighborhood_names=(names)
    names[0].split(',').each do |name|
      next if name.blank?
      if neighborhood = Neighborhood.find_by_name(name)
        search_neighborhoods.build neighborhood_id: neighborhood.id
      end
    end
  end

My SearchController.rb

我SearchController.rb

  def autocomplete_neighborhood_name
    @neighborhood = Neighborhood.select("id, name").where("name LIKE ?", "#{params[:name]}%").order(:name).limit(10)

    respond_to do |format|
      format.json { render json: @neighborhood , :only => [:id, :name] }
    end    
  end

This is what a request looks like right now - which shows that no search_neighborhood records are being created:

这就是现在的请求——显示没有创建search_neighborhood记录:

Started POST "/searches" for 127.0.0.1 at 2013-03-06 04:09:55 -0500
Processing by SearchesController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"7SeA=", "search"=>{"boro_id"=>"", "neighborhood_names"=>"1416,1394", "property_type_id"=>"", "min_price"=>"", "max_price"=>"", "num_bedrooms"=>"", "num_bathrooms"=>""}}
  Neighborhood Load (0.5ms)  SELECT "neighborhoods".* FROM "neighborhoods" WHERE "neighborhoods"."name" = '1' LIMIT 1
   (0.3ms)  BEGIN
  SQL (0.8ms)  INSERT INTO "searches" ("amenity_id", "boro_id", "created_at", "keywords", "listing_type_id", "max_price", "min_price", "neighborhood_id", "num_bathrooms", "num_bedrooms", "property_type_id", "square_footage", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13) RETURNING "id"  [["amenity_id", nil], ["boro_id", nil], ["created_at", Wed, 06 Mar 2013 09:09:55 UTC +00:00], ["keywords", nil], ["listing_type_id", nil], ["max_price", nil], ["min_price", nil], ["neighborhood_id", nil], ["num_bathrooms", nil], ["num_bedrooms", nil], ["property_type_id", nil], ["square_footage", nil], ["updated_at", Wed, 06 Mar 2013 09:09:55 UTC +00:00]]
   (32.2ms)  COMMIT
Redirected to http://localhost:3000/searches/29

3 个解决方案

#1


24  

The select2 plugin supports auto-completion. You can use the native auto-completion as follows:

select2插件支持自动完成。您可以使用本机自动完成如下:

<%= f.input_field :ac_neighborhood_ids, 
      data: { 
        placeholder: "Where do you want to live?",
        saved: @search.neighborhoods.to_json,
        url: autocomplete_neighborhood_name_searches_path
      }, 
      input_html:  { class: "span8 ac-select2" }
%>

Javscript

Javscript

$(document).ready(function() {  
  $('.ac-select2').each(function() {
    var url = $(this).data('url'); 
    var placeholder = $(this).data('placeholder'); 
    var saved = jQuery.parseJSON($(this).data('saved'));
    $(this).select2({
      minimumInputLength: 2,
      multiple: true,
      placeholder : placeholder,
      allowClear: true,
      ajax: {
        url: url,
        dataType: 'json',
        quietMillis: 500,
        data: function (term) {
          return {
            name: term
          };
        },
        results: function (data) {
          return {results: data};
        }
      },

      formatResult: function (item, page) {
        return item.name; 
      },

      formatSelection: function (item, page) {
        return item.name; 
      },

      initSelection : function (element, callback) {
        if (saved) {
          callback(saved);
        }
      }

    });
  });
});

Make sure the action at autocomplete_neighborhood_name_searches_path returns a json array of hashes. Each hash should contain id and name fields. The term for auto-completion is passed via the query parameter name.

确保autocomplete_neighborhood_name_searches_path的操作返回一个散列的json数组。每个散列应该包含id和name字段。自动完成的术语通过查询参数名传递。

  def autocomplete_neighborhood_name
    @neighborhood = Neighborhood.select("id, name").where("name LIKE ?", "#{params[:name]}%").order(:name).limit(10)

    respond_to do |format|
      format.json { render json: @neighborhood , :only => [:id, :name] }
    end    
  end

Your search model:

你的搜索模型:

class Search

  attr_accessor :ac_neighborhood_ids

  has_many :search_neighborhoods
  has_many :neighborhoods, through: :search_neighborhoods

  def ac_neighborhood_ids
    neighborhood_ids.join(",")
  end

  def ac_neighborhoods
    neighborhoods.map{|n| {:id => n.id, :name => n.name}}
  end

  def ac_neighborhood_ids=(ids)
    search_neighborhoods.clear # remove the old values
    ids.split(',').select(&:present?).map do |neighborhood_id|
      search_neighborhoods.build neighborhood_id: neighborhood_id
    end
  end

end    

#2


1  

I believe you need to attach select either to select tag (then it reads the data from it) or to input hidden tag, then you need to provide 'query' function. In your case it is attached to an input tag, and thus looks for a query function. Try setting as: :select on your f.input_field call.

我认为您需要附加select来选择标签(然后它从标签中读取数据)或者输入隐藏标签,然后您需要提供“查询”功能。在您的示例中,它附加到一个输入标记,因此查找查询函数。尝试设置为:选择f。input_field电话。

#3


0  

Use as: :select with collection is regular way to for select2. Binding autocomplete on select2 is a javascript matter.

使用as::select with collection是select2的常规方法。在select2上绑定自动完成是一个javascript问题。

This is my code sample. but does not have autocompletion. https://gist.github.com/kuboon/f692d9a844c0ff5877c8

这是我的代码示例。但没有自动补全。https://gist.github.com/kuboon/f692d9a844c0ff5877c8

#1


24  

The select2 plugin supports auto-completion. You can use the native auto-completion as follows:

select2插件支持自动完成。您可以使用本机自动完成如下:

<%= f.input_field :ac_neighborhood_ids, 
      data: { 
        placeholder: "Where do you want to live?",
        saved: @search.neighborhoods.to_json,
        url: autocomplete_neighborhood_name_searches_path
      }, 
      input_html:  { class: "span8 ac-select2" }
%>

Javscript

Javscript

$(document).ready(function() {  
  $('.ac-select2').each(function() {
    var url = $(this).data('url'); 
    var placeholder = $(this).data('placeholder'); 
    var saved = jQuery.parseJSON($(this).data('saved'));
    $(this).select2({
      minimumInputLength: 2,
      multiple: true,
      placeholder : placeholder,
      allowClear: true,
      ajax: {
        url: url,
        dataType: 'json',
        quietMillis: 500,
        data: function (term) {
          return {
            name: term
          };
        },
        results: function (data) {
          return {results: data};
        }
      },

      formatResult: function (item, page) {
        return item.name; 
      },

      formatSelection: function (item, page) {
        return item.name; 
      },

      initSelection : function (element, callback) {
        if (saved) {
          callback(saved);
        }
      }

    });
  });
});

Make sure the action at autocomplete_neighborhood_name_searches_path returns a json array of hashes. Each hash should contain id and name fields. The term for auto-completion is passed via the query parameter name.

确保autocomplete_neighborhood_name_searches_path的操作返回一个散列的json数组。每个散列应该包含id和name字段。自动完成的术语通过查询参数名传递。

  def autocomplete_neighborhood_name
    @neighborhood = Neighborhood.select("id, name").where("name LIKE ?", "#{params[:name]}%").order(:name).limit(10)

    respond_to do |format|
      format.json { render json: @neighborhood , :only => [:id, :name] }
    end    
  end

Your search model:

你的搜索模型:

class Search

  attr_accessor :ac_neighborhood_ids

  has_many :search_neighborhoods
  has_many :neighborhoods, through: :search_neighborhoods

  def ac_neighborhood_ids
    neighborhood_ids.join(",")
  end

  def ac_neighborhoods
    neighborhoods.map{|n| {:id => n.id, :name => n.name}}
  end

  def ac_neighborhood_ids=(ids)
    search_neighborhoods.clear # remove the old values
    ids.split(',').select(&:present?).map do |neighborhood_id|
      search_neighborhoods.build neighborhood_id: neighborhood_id
    end
  end

end    

#2


1  

I believe you need to attach select either to select tag (then it reads the data from it) or to input hidden tag, then you need to provide 'query' function. In your case it is attached to an input tag, and thus looks for a query function. Try setting as: :select on your f.input_field call.

我认为您需要附加select来选择标签(然后它从标签中读取数据)或者输入隐藏标签,然后您需要提供“查询”功能。在您的示例中,它附加到一个输入标记,因此查找查询函数。尝试设置为:选择f。input_field电话。

#3


0  

Use as: :select with collection is regular way to for select2. Binding autocomplete on select2 is a javascript matter.

使用as::select with collection是select2的常规方法。在select2上绑定自动完成是一个javascript问题。

This is my code sample. but does not have autocompletion. https://gist.github.com/kuboon/f692d9a844c0ff5877c8

这是我的代码示例。但没有自动补全。https://gist.github.com/kuboon/f692d9a844c0ff5877c8