Skip to content

Instantly share code, notes, and snippets.

@SeriouslyAwesome
Forked from tylerhunt/Gemfile
Last active April 1, 2024 20:50
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save SeriouslyAwesome/0cf0008150429d4713c62ca6d4a0deee to your computer and use it in GitHub Desktop.
Save SeriouslyAwesome/0cf0008150429d4713c62ca6d4a0deee to your computer and use it in GitHub Desktop.
ActiveAdmin association autocomplete without complicated plugins.
@import 'active_admin/mixins';
@import 'active_admin/base';
@import 'jquery.ui.autocomplete';
#= require active_admin/base
#= require jquery.ui.autocomplete
$ ->
$('.autocomplete').each (index, input) ->
$input = $(input)
$hiddenInput = $($(input).data('hidden-input'))
$input
.autocomplete
minLength: 3
delay: 600
source: (request, response) ->
$.ajax
url: $input.data('url')
dataType: 'json'
data:
term: request.term
success: (data) -> response(data)
select: (event, ui) ->
$input.val(ui.item.label)
$hiddenInput.val(ui.item.id)
false
.data('ui-autocomplete')._renderItem = (ul, item) ->
$('<li></li>')
.data('item.autocomplete', item)
.append('<a>' + item.label + '</a>')
.appendTo(ul)
# app/admin/inputs/autocomplete_input.rb
class AutocompleteInput
include Formtastic::Inputs::Base
include Formtastic::Inputs::Base::Stringish
include ActionDispatch::Routing::UrlFor
include Rails.application.routes.url_helpers
def to_html
input_wrapping do
label_html <<
builder.text_field(method, input_html_options) <<
builder.hidden_field(id_method, id: hidden_input_id, required: nil, autofocus: nil)
end
end
def input_html_options
{
class: 'js-autocomplete',
value: object.send(method)&.display_name,
data: {
url: search_url,
hidden_input: "##{hidden_input_id}",
original_value: object.send(method)&.display_name
}
}.merge(super)
end
def name_method
"#{method}_name".to_sym
end
def id_method
"#{method}_id".to_sym
end
def hidden_input_id
"#{object.class.name.downcase}_#{id_method}"
end
def search_url
options[:url] || url_for(action: 'search', controller: "nucleus/#{method.to_s.pluralize}")
end
end
class AutocompleteSerializer < ActiveModel::Serializer
attribute :id
attribute :label
private
def label
object.name
end
end
gem 'active_model_serializers'
gem 'activeadmin'
gem 'jquery-ui-rails'
ActiveAdmin.register Post do
form do |f|
f.inputs 'Details' do
# standard usage
f.input :user, as: :autocomplete
# or for associations that don't resolve directly to the model name or
# an ActiveAdmin resource that is aliased like ActiveAdmin.register Widget, as: 'Gadget' do
f.input :author, as: :autocomplete, url: search_admin_users_path
end
end
end
ActiveAdmin.register User do
collection_action :search, method: :get do
users = User.where('LOWER(name) ILIKE ?', "#{params[:term]}%")
render json: users, each_serializer: AutocompleteSerializer, root: false
end
end
@ianpetzer
Copy link

Thanks for this. Very helpful.
FYI, I made following changes to get this working:
I changed the controller from nucleus to admin
I had to change the selector in the JS method to return $('.autocomplete input')
and my scss import looks like:
@import 'jquery-ui/core';
@import 'jquery-ui/autocomplete';
@import 'jquery-ui/theme';
when using the jquery-ui-rails gem

@leandro
Copy link

leandro commented Jul 20, 2018

@SeriouslyAwesome That's really nice. I just recommend you to avoid using include Rails.application.routes.url_helpers. Instead create a private method and use it to access the named routes or other routes methods:

def url_helpers
  Rails.application.routes.url_helpers
end

Then you can do this: url_helpers.url_for(...)

@carlsmith-aob
Copy link

@SeriouslyAwesome how might we alter this for use with filters rather than inputs?

@mehmetaydogduu
Copy link

Nice! But looks messy. How about packing as a gem?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment