Skip to content

Instantly share code, notes, and snippets.

@jschwertfeger
Created October 5, 2012 20:49
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jschwertfeger/3842296 to your computer and use it in GitHub Desktop.
Save jschwertfeger/3842296 to your computer and use it in GitHub Desktop.
A jQuery autocomplete widget for forms where the underlying model references another model via ID
/*
* Unobtrusive autocomplete for model associations.
*
* For instance, assume you have a model `Task' and a model `User'. The task has
* an attribute user_id which associates the user who is assigned to the task.
* This widget allows you to build a form for tasks where the association is
* represented by a hidden user_id field that gets populated through an
* autocomplete text field.
*
* To use it you just have to include the tag attributes for the autocomplete
* URL and, optionally, the display value for the current associated object.
*
* Example:
* <input type="text" name="task[user_id]" id="task_user_id" value="123"
* data-autocomplete-url="/url/to/autocomplete" data-autocomplete-value="Joe Doe">
*
* You can apply the widget to a specific input field or to all autocomplete
* fields in the document:
*
* <script>
* $(function()) {
* // Just this field
* $('#task_user_id').autocompleteAssociation();
*
* // or every field
* $('input[data-autocomplete-url]').autocompleteAssociation();
* };
* </script>
*
* The widget will hide the element it is applied to and insert an autocomplete
* input field right after it. As the user enters a term into the field jQuery
* will execute a GET request to the configured autocomplete URL,
* passing along the entered term as a query parameter `term'.
*
* The server then has to return an array of objects with id and value
* properties:
*
* [ { id: 123, value: "Joe Doe" }, ... ]
*
* If one of the returned items is selected the widget will store the item's ID
* as the value of the original, now hidden, element.
*/
(function ($) {
$.widget("ui.autocompleteAssociation", {
_create:function () {
var thisElement = this.element;
var storeAssociation = function (event, ui) {
if (ui.item) {
thisElement.val(ui.item.id);
thisElement.attr('data-autocomplete-value', ui.item.value);
} else {
thisElement.val('');
thisElement.attr('data-autocomplete-value', '');
$(this).val('');
}
};
thisElement.hide();
var input = $("<input>")
.insertAfter(thisElement)
.attr('id', thisElement.attr('id') + '_autocomplete')
.val(thisElement.attr('data-autocomplete-value') || '')
.addClass("ui-state-default ui-autocomplete-association")
.autocomplete({
source:thisElement.attr('data-autocomplete-url') || null,
select:storeAssociation,
change:storeAssociation
});
},
destroy:function () {
this.element.show();
$.Widget.prototype.destroy.call(this);
}
});
})(jQuery);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment