Last active
March 2, 2020 00:32
-
-
Save smoil/5061616 to your computer and use it in GitHub Desktop.
Ajax select/multi select in Rails using Select2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Account < ActiveRecord::Base | |
def self.search(name = nil) | |
# search logic | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class AccountsController < ApplicationController | |
def search | |
# this returns a hash of search results | |
records = RecordSearcher.call(Account.by_name, params) | |
render json: records.to_json, callback: params[:callback] | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# bind to selectors | |
jQuery -> | |
account_args = | |
url: "/accounts/search.json" | |
options: | |
placeholder: "Search for an account" | |
$(".account-select").ajaxSelect(account_args.url, account_args.options) | |
$(".account-multi-select").ajaxSelect( | |
account_args.url, | |
placeholder: account_args.options | |
multiple: true | |
) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/ form input for user.stringy_account_ids, note data is set to pre-render exisiting results | |
= f.label :stringy_account_ids, "Accounts" | |
= f.hidden_field :stringy_account_ids, class: "account-multi-select", data: { records: f.object.accounts.select(["accounts.id","accounts.name"]) } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# customize options to suit your needs and/or forgo creating a first class jquery function | |
jQuery.fn.ajaxSelect = (url, options) -> | |
defaults = | |
placeholder: "Search for a record" | |
formatter: (record) -> | |
record.name | |
multiple: false | |
allow_clear: true | |
settings = $.extend(defaults, options) | |
this.select2 | |
initSelection: (elm, callback) -> | |
results = $(elm).data "records" | |
callback(results) | |
placeholder: settings.placeholder | |
allowClear: settings.allow_clear | |
minimumInputLength: 3 | |
multiple: settings.multiple | |
ajax: | |
url: url | |
dataType: "jsonp" | |
quietMillis: 100 | |
data: (term, page) -> | |
query: term | |
limit: 10 | |
page: page | |
results: (data, page) -> | |
more = (page * 10) < data.total | |
results: data.records | |
more: more | |
formatResult: settings.formatter | |
formatSelection: settings.formatter |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# a simple class to generate search results, you can provide a block if you have different data attributes | |
class RecordSearcher | |
attr_reader :records | |
def initialize(records, params = {}) | |
unless records.respond_to? :search | |
raise ArgumentError, "records must repond to .search" | |
end | |
default_params = { | |
query: nil, | |
page: nil, | |
limit: nil | |
} | |
params.reverse_merge!(default_params) | |
@records = records.search(params[:query]).page(params[:page]) | |
.per(params[:limit]) | |
end | |
def call(&block) | |
{ | |
total: records.total_count, | |
records: records.map do |record| | |
if block_given? | |
block.call(record) | |
else | |
{ name: record.name, id: record.id } | |
end | |
end | |
} | |
end | |
def self.call(records, params = {}, &block) | |
new(records, params).call(&block) | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# invoking in a class will add methods stringy_whatever_ids, and stringy_whatever_ids= | |
module StringyAssociationIds | |
def stringy_ids(association) | |
define_method("stringy_#{association}_ids=") do |comma_seperated_ids| | |
self.send("#{association}_ids=", comma_seperated_ids.to_s.split(",")) | |
end | |
define_method("stringy_#{association}_ids") do | |
send("#{association}_ids").join(",") | |
end | |
end | |
end | |
ActiveRecord::Base.extend(StringyAssociationIds) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class User < ActiveRecord::Base | |
has_many :accounts | |
stringy_ids :account | |
end |
Can you make a tutorial on it because it is not self-explanatory
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is great, thanks for posting. I haven't had any luck attaching this to a form field in a form without an object. I have a search form_tag which sends a get request without an object, so . I was using select2 without ajax successfully by calling plain .select2 on this input:
<%= select_tag(:location_id, options_from_collection_for_select(@Locations, :id, :name, @location_ids), :class => "location_multi", :multiple => true)%>
Any idea how one would apply your logic to a hidden_field_tag to get it to submit multiple values correctly?
In case anyone else running into similar issues comes across this page, I've pasted below how you would alter @smoil's approach if multiple: false.
form: