Background
Currently in a project of mine I am using jQuery autocomplete for a few fields.
To provide context, the application records Runs. Each Run must have a Route associated with it. A Route meaning, where the user ran.
When the user types in a Route, a list of their Routes gets displayed by the autocomplete options, but the database requires the RouteID for validation.
To compensate for this, I stored the RouteID in a HiddenFor HtmlHelper. When the user selects the route from the autocomplete, the HiddenFor gets assigned.
What my problem is
If the user types in the full name of the Route, instead of selecting it from the autocomplete list or enters a Route that does not exist, the HiddenFor will not get assigned. When this happens, I have to find the Route by its name and validate that it exists on the server.
I would like to not have to create this work-around for every autocomplete.
The bottom line
Is there anyway to make the autocomplete act more like a select list? I want the user to have no choice but to select the text of one option from the autocomplete list, and have the value of the selected option is sent to the server.
If I have to stick to the HiddenFor method, is there at least a way to force the user to select an option from the autocomplete list?
Below is the code I am currently using
Mark-up
@Html.LabelFor(model => model.RouteID, "Route")
<input type="text" data-autocomplete-url="@Url.Action("../Route/GetRoutesByUser")" />
@Html.HiddenFor(m => m.RouteID)
jQuery
$('*[data-autocomplete-url]')
.each(function () {
$(this).autocomplete({
source: $(this).data("autocomplete-url"),
minLength: 2,
select: function (event, ui) {
log(ui.item.id, ui.item.name);
}
});
});
Code
public ActionResult GetRoutesByUser(string term)
{
var routeList = db.Routes.Where(r => r.Name.Contains(term))
.Take(5)
.Select(r => new { id = r.RouteID, label = r.Name, name = "RouteID"});
return Json(routeList, JsonRequestBehavior.AllowGet);
}
Alright, after a lot of fiddling around I came up with the following implementation:
The code below is a
HtmlHelpercalled@Html.AutocompleteWithHiddenFor. The HtmlHelper will create aninputHTML element with adata-autocomplete-urlproperty based on thecontrollerandactionpassed in.If the
inputelement needs avaluethen you can pass that in as well. AHiddenForwill be created for theModelproperty passed in and aValidationMessageForwill be created for theModelas well.Now all I have to do is use
@Html.AutocompleteWithHiddenFor, and pass in whatever expression I need with the controller and action (and possibly the value) to get the autocomplete functionality and have the ID pass to the server instead of the text.jQuery
AutocompleteHelper class
View
Or if it needs a value