public
Last active

A jQuery autocomplete widget for forms where the underlying model references another model via ID

  • Download Gist
autocomplete_association.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
/*
* 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);

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.