2

背景
現在、私のプロジェクトではautocomplete、いくつかのフィールドに jQuery を使用しています。

コンテキストを提供するために、アプリケーションはRuns. それぞれに が関連付けられているRun必要があります。Routeユーザーが走った場所のRoute意味。

ユーザーが を入力するRouteと、そのリストがオプションRoutesによって表示されautocompleteますが、データベースではRouteID検証のために が必要です。

これを補うためRouteIDに、HiddenForHtmlHelper に保存しました。ユーザが からルートを選択するautocompleteと、HiddenForが割り当てられます。

私の問題は何ですか? ユーザーがリストから選択するか、存在しない を入力する代わりに
、 のフルネームを入力すると、は割り当てられません。これが発生した場合、その名前でを見つけて、サーバー上に存在することを確認する必要があります。RouteautocompleteRouteHiddenForRoute

この回避策を毎回作成する必要がないようにしたいと思いますautocomplete


結論 とにかく、そのautocomplete行為をより多くのようにする方法はありますselect listか?ユーザーには、autocompleteリストから 1 つのオプションのテキストを選択する以外に選択肢がなく、選択したオプションの値がサーバーに送信されるようにしたいと考えています。

メソッドに固執する必要HiddenForがある場合、少なくともユーザーにautocompleteリストからオプションを選択させる方法はありますか?


以下は私が現在使用しているコードです

マークアップ

@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);
            }
        });
    });

コード

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);
}
4

2 に答える 2

1

これにはイベントを使用し、アイテムが選択されていない場合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.
                }
            }
        });
    });
});

例: http://jsfiddle.net/urEzm/

于 2012-06-20T18:32:00.127 に答える
1

さて、いろいろいじった後、次の実装を思いつきました。

以下のコードHtmlHelper@Html.AutocompleteWithHiddenFor. HtmlHelper は、渡された に基づくプロパティをinput持つ HTML 要素を作成します。data-autocomplete-urlcontrolleraction

input要素に が必要な場合は、valueそれを渡すこともできます。渡されたプロパティHiddenForに対して が作成され、に対しても が作成されます。ModelValidationMessageForModel

あとは、 を使用@Html.AutocompleteWithHiddenForし、コントローラーとアクション (および場合によっては値) で必要な式を渡して、オートコンプリート機能を取得し、 text の代わりに ID をサーバーに渡すだけです

jQuery

$(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);
                }
            }
        });
    });
});

AutocompleteHelper クラス

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);
     }
}

意見

@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) 
于 2012-06-22T22:53:31.737 に答える