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
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Creare una libreria CSS universale: Immagini
Creare un webhook in Azure DevOps
Eseguire query per recuperare il padre di un record che sfrutta il tipo HierarchyID in Entity Framework
Migliorare i tempi di risposta di GPT tramite lo streaming endpoint in ASP.NET Core
Introduzione alle Container Queries
Utilizzare un numero per gestire la concorrenza ottimistica con SQL Server ed Entity Framework
Eliminare una project wiki di Azure DevOps
Utilizzare una qualunque lista per i parametri di tipo params in C#
Eseguire query manipolando liste di tipi semplici con Entity Framework Core
Evitare (o ridurre) il repo-jacking sulle GitHub Actions
Hosting di componenti WebAssembly in un'applicazione Blazor static
Esporre i propri servizi applicativi con Semantic Kernel e ASP.NET Web API