问题
I've a form in a basic task management app which allows Tasks to be assigned to Users (task belongs_to user). I'm using Simple Form for this.
Currently, the association is populated in the typical manner, with a dropdown list of users as such: <%= f.association :user, label_method: :name, value_method: :id, include_blank: false %>
.
However, as the number of Users grows, I'm looking to change this to an autocomplete form field to find users. I've tried following the Railscast on the subject, though it doesn't use Simple Form and isn't working on my implementation.
Here's my form, model and .coffee code:
Form
<%= simple_form_for @task do |f| %>
...
<%= f.input :user_name, as: :search, data:
{autocomplete_source: User.pluck(:name)} %>
...
<%= f.button :submit %>
<% end %>
Model
# Virtual attribute for autocomplete form field
def user_name
user.try(:name)
end
def user_name=(name)
self.user = User.find_by_name(name) if name.present?
end
tasks.coffee
jQuery ->
$('#task_user_name').autocomplete
source: $('#task_user_name').data('autocomplete-source')
This generates the following HTML:
<input class="string search optional form-control
ui-autocomplete-input ui-autocomplete-loading" type="search"
value="Robert Strong" name="task[user_name]" id="task_user_name"
autocomplete="off">
Though the following error in the dev tools console:
Uncaught TypeError: this.source is not a function
Concerned about the autocomplete="off"
within the HTML and can't imagine the TypeError helps much!
I'm stumped, so would greatly appreciate any advice on getting this working! Thanks in advance, let me know what you think, Steve.
回答1:
autocomplete_source is expecting an array or a URL that when called returns JSON with the results that match the query. http://api.jqueryui.com/autocomplete/#option-source
Right now you have
<%= f.input :user_name, as: :search, data:
{autocomplete_source: User.pluck(:name)} %>
Thats probably going to return a string for javascript. So you could change it to something like:
<%= f.input :user_name, as: :search, data:
{autocomplete_source: User.pluck(:name).to_json} %>
And then parse that JSON when setting up your autocomplete:
jQuery ->
$('#task_user_name').autocomplete
source: JSON.parse($('#task_user_name').data('autocomplete-source'))
In the long run though (when you have a lot of users) this will impact the load time of your page significantly. You should really instead follow that railscast and put a URL as the autocomplete source:
<%= f.input :user_name, as: :search, data:
{autocomplete_source: users_path} %>
Make sure to add the json render path to the index action on your users controller.
If your index action is used for other things too you can use respond_to
:
# users_controller
def index
@users = User.order(:name)
@users = @users.where("name like ?", "%#{params[:term]}%") if params[:term]
respond_to do |format|
format.html # index.html.erb
format.json { render :json => @users.map(&:name) }
end
end
回答2:
In addition to Oliver's answer I had to:
<%= f.input :user_name, as: :search, input_html: {class: 'ui-autocomplete-input', data: {autocomplete_source: users_path} }%>
To make it work with Simple_Form.
来源:https://stackoverflow.com/questions/29779009/ruby-on-rails-simple-form-autocomplete-association-search