MVC3 jQuery自动完成-用户必须选择选项,选项ID发送到服务器
背景MVC3 jQuery自动完成-用户必须选择选项,选项ID发送到服务器,jquery,asp.net,asp.net-mvc,asp.net-mvc-3,jquery-ui-autocomplete,Jquery,Asp.net,Asp.net Mvc,Asp.net Mvc 3,Jquery Ui Autocomplete,背景 目前在我的一个项目中,我使用jQueryautocomplete处理一些字段 要提供上下文,应用程序记录将运行。每次运行都必须有一条与之相关联的路线。一条路线意思是,用户在那里跑步 当用户键入路线时,其路线的列表将通过自动完成选项显示,但数据库需要路线ID进行验证 为了补偿这一点,我将RouteID存储在HiddenForHtmlHelper中。当用户从autocomplete选择路线时,将分配HiddenFor 我的问题是什么 如果用户键入路线的全名,而不是从自动完成列表中选择它或输
目前在我的一个项目中,我使用jQuery
autocomplete
处理一些字段
要提供上下文,应用程序记录将运行。每次运行
都必须有一条与之相关联的路线
。一条路线
意思是,用户在那里跑步
当用户键入路线
时,其路线
的列表将通过自动完成
选项显示,但数据库需要路线ID
进行验证
为了补偿这一点,我将RouteID
存储在HiddenFor
HtmlHelper中。当用户从autocomplete
选择路线时,将分配HiddenFor
我的问题是什么
如果用户键入路线的全名
,而不是从自动完成
列表中选择它或输入一个不存在的路线
,则不会分配隐藏的
。当发生这种情况时,我必须按其名称查找路由
,并验证它是否存在于服务器上
我希望不必为每个自动完成
创建此工作环境
底线
是否有办法使自动完成
更像一个选择列表
?我希望用户别无选择,只能从autocomplete
列表中选择一个选项的文本,并将所选选项的值发送到服务器
如果我必须坚持使用HiddenFor
方法,是否至少有办法强制用户从autocomplete
列表中选择一个选项
下面是我目前使用的代码
加价
@Html.LabelFor(model => model.RouteID, "Route")
<input type="text" data-autocomplete-url="@Url.Action("../Route/GetRoutesByUser")" />
@Html.HiddenFor(m => m.RouteID)
代码
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);
}
我将使用change
事件进行此操作,如果未选择项目,则清除input
的值:
$('*[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);
},
change: function (event, ui) {
if (!ui.item) {
this.value = '';
} else {
// Populate your hidden input.
}
}
});
});
});
示例:好吧,在反复尝试之后,我想出了以下实现:
下面的代码是一个名为@Html.AutocompleteWithHiddenFor
的HtmlHelper
。HtmlHelper将基于传入的控制器
和操作
创建一个输入
HTML元素,该元素具有数据自动完成url
属性
如果输入
元素需要一个值
,那么您也可以传入该值。将为传入的Model
属性创建HiddenFor
,并为Model
创建ValidationMessageFor
现在,我所要做的就是使用@Html.AutocompleteWithHiddenFor
,并通过控制器和操作(可能还有值)传入所需的任何表达式,以获得自动完成功能,并将ID传递给服务器,而不是文本
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);
}
});
});
$(function () {
function log(id, name) {
var hidden = $('#' + name);
hidden.attr("value", id);
}
$('*[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);
},
change: function (event, ui) {
if (!ui.item) {
this.value = '';
} else {
log(ui.item.id, ui.item.name);
}
}
});
});
});
自动完成助手类
public static class AutocompleteHelper
{
/// <summary>
/// Given a Model's property, a controller, and a method that belongs to that controller,
/// this function will create an input html element with a data-autocomplete-url property
/// with the method the autocomplete will need to call the method. A HiddenFor will be
/// created for the Model's property passed in, so the HiddenFor will be validated
/// and the html input will not.
/// </summary>
/// <returns></returns>
public static MvcHtmlString AutocompleteWithHiddenFor<TModel, TProperty>(this HtmlHelper<TModel> html, Expression<Func<TModel, TProperty>> expression, string controllerName, string actionName, object value = null)
{
// Create the URL of the Autocomplete function
string autocompleteUrl = UrlHelper.GenerateUrl(null, actionName,
controllerName,
null,
html.RouteCollection,
html.ViewContext.RequestContext,
includeImplicitMvcValues: true);
// Create the input[type='text'] html element, that does
// not need to be aware of the model
String textbox = "<input type='text' data-autocomplete-url='" + autocompleteUrl + "'";
// However, it might need to be have a value already populated
if (value != null)
{
textbox += "value='" + value.ToString() + "'";
}
// close out the tag
textbox += " />";
// A validation message that will fire depending on any
// attributes placed on the property
MvcHtmlString valid = html.ValidationMessageFor(expression);
// The HiddenFor that will bind to the ID needed rather than
// the text received from the Autocomplete
MvcHtmlString hidden = html.HiddenFor(expression);
string both = textbox + " " + hidden + " " + valid;
return MvcHtmlString.Create(both);
}
}
或者如果它需要一个值
非常感谢你带我去参加变革活动。它在可用性方面确实有所帮助。经过一番周折,我想出了自己的实现,为这个过程提供了一个可重用的HtmlHelper;并使用System.Web.Mvc.Html;当然否则它就不会建造。我省略了它们,因为代码已经足够长了。VisualStudio也会让您知道需要导入哪些库。
@Html.LabelFor(model => model.RouteID, "Route")
@Html.AutocompleteWithHiddenFor(model => model.RouteID, "Route", "GetRoutesByUser")
@Html.LabelFor(model => model.Route, "Route")
@Html.AutocompleteWithHiddenFor(model => model.RouteID, "Route", "GetRoutesByUser", @Model.RouteName)