Un HtmlHelper per sfruttare la DataList di HTML 5 in ASP.NET MVC

di Marco De Sanctis, in ASP.NET MVC,

Tra le varie novità di HTML5, una che risulta estremamente utile è l'elemento DataList, che implementa un comportamento simile a quello di una ComboBox: questo tag va utilizzato in concomitanza con un input testuale ed è in grado di fornire una serie di suggerimenti o di valori predefiniti, che poi possono essere comunque modificati dall'utente. Possiamo vederne un esempio in figura.


Il markup necessario per realizzare un effetto del genere consiste nell'abbinare, tramite l'attributo list, un input[type=text] alla corrispondente DataList:

<input type="text" ... list="nome_dataList" />;
<datalist id="nome_dataList">
  <option value="option1">option1</option>
  <option value="option2">option2</option>
  <option value="option3">option3</option>
</datalist>

ASP.NET MVC non presenta un html helper nativo per realizzare un tag di questo tipo, ma possiamo costruirne uno in maniera abbastanza semplice. Tutto ciò che dobbiamo fare, infatti, è creare un extension method con la signature seguente:

public static MvcHtmlString DataListFor<TModel, TProperty>(
  this HtmlHelper<TModel> html, 
  Expression<Func<TModel, TProperty>> expression, 
  IEnumerable<SelectListItem> selectList, object htmlAttributes)
{ ... }

Visto che, in fin dei conti, dobbiamo realizzare un box di testo, questo metodo contiene tutti i parametri che troviamo nell'helper TextBoxFor (sia l'expression che l'oggetto htmlAttributes), ma richiede anche una lista di SelectListItem, che poi utilizzeremo per popolare l'elenco a scomparsa.

Passando all'implementazione, il nostro primo compito è quello di generare un id univoco per la datalist, e di referenziarlo dalla TextBox:

var listId = ExpressionHelper.GetExpressionText(expression) + "_dataList";

if (htmlAttributes == null)
    htmlAttributes = new object();

RouteValueDictionary dictionary = new RouteValueDictionary(htmlAttributes);
dictionary.Add("list", listId);

var input = html.TextBoxFor(expression, dictionary);

A questo punto non ci resta che creare, tramite TagBuilder, la parte di markup mancante, ossia quella relativa al tag DataList:

var dataList = new TagBuilder("DataList");
dataList.GenerateId(listId);

StringBuilder items = new StringBuilder();
foreach (var item in selectList)
{
    items.AppendLine(ItemToOption(item));
}

dataList.InnerHtml = items.ToString();

return new MvcHtmlString(input + dataList.ToString());

Nel codice precedente, abbiamo sfruttato il medesimo listId per associare questo identificativo alla DataList. Successivamente, per ogni elemento SelectListItem fornito, generiamo il corrispondente tag option, da aggiungere all'InnerHtml della DataList stessa. Questo compito è eseguito dal metodo ItemToOption:

private static string ItemToOption(SelectListItem item)
{
    TagBuilder builder = new TagBuilder("option");
    builder.MergeAttribute("value", item.Value);
    builder.SetInnerText(item.Text);

    return builder.ToString(TagRenderMode.Normal);
}

Con questi semplici passaggi, siamo stati in grado di confezionare un HtmlHelper che rende davvero immediato l'utilizzo di questo nuovo elemento, come possiamo notare dal codice seguente:

<div class="col-md-10">
    @Html.DataListFor(model => model.Title, this.Model.AvailableTitles, null)
</div>

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti

I più letti di oggi