Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

MVC HtmlHelper for HTML5 datalist Tag

4.33/5 (2 votes)
8 Sep 2015CPOL 27.5K  
MVC HtmlHelper for HTML5 datalist Tag

Introduction

Recently, I used the datalist tag in my ASP.NET MVC application and I decided to create an MVC HtmlHelper extension method to achieve this.

This is what the HTML of a datalist tag looks like:

HTML
<input list="browsers">

<datalist id="browsers">
  <option value="Internet Explorer">
  <option value="Firefox">
  <option value="Chrome">
  <option value="Opera">
  <option value="Safari">
</datalist>

and with the extension method outlined in this tip, you should be able to generate both tags using the following Razor syntax:

VB.NET
@Html.DataListInputFor(Function(m) m.CountryName, Model.GetCountries)

Using the Code

The HtmlHelper will generate the input tag and associated datalist tag. Let's take a look at what the HtmlHelper looks like:

VB.NET
Option Strict On
Option Explicit On

Imports System.Linq.Expressions
Imports System.Runtime.CompilerServices

Namespace Mvc.HtmlHelpers
    ''' <summary>
    ''' Create an input and associated datalist tag. See:
    ''' http://www.w3schools.com/tags/tag_datalist.asp
    ''' </summary>
    ''' <remarks></remarks>
    Public Module DataListInputExtensions
        <Extension>
        Public Function DataListInputFor(Of TModel, TProperty)(
            htmlHelper As HtmlHelper(Of TModel),
            expression As Expression(Of Func(Of TModel, TProperty)),
            dataListItems As IEnumerable(Of String)) As IHtmlString
            
            Return htmlHelper.DataListInputFor(expression, dataListItems, Nothing)
        End Function

        <Extension>
        Public Function DataListInputFor(Of TModel, TProperty)(
            htmlHelper As HtmlHelper(Of TModel),
            expression As Expression(Of Func(Of TModel, TProperty)),
            dataListItems As IEnumerable(Of String),
            htmlAttributes As Object) As IHtmlString

            Dim html As New StringBuilder

            Dim input As New TagBuilder("input")
            input.MergeAttributes(htmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes))

            ' Create the input tag which will reference the datalist.
            Dim metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData)
            Dim fullName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(
                ExpressionHelper.GetExpressionText(expression))

            input.GenerateId(fullName)
            input.Attributes("name") = fullName
            'Make sure ToString won't cause an exception of the Model is null.
            input.Attributes("value") = If(metadata.Model IsNot Nothing,
                                           metadata.Model.ToString,
                                           String.Empty)

            ' Create the datalist tag which contains the list of searchable items.
            Dim dataList As New TagBuilder("datalist")
            dataList.GenerateId(String.Format("datalist_{0}", fullName))
            input.Attributes("list") = dataList.Attributes("id")

            ' Populate the datalist with options.
            Dim optionsHtml As New StringBuilder
            For Each item In dataListItems
                Dim opt As New TagBuilder("option")
                opt.Attributes("value") = item
                optionsHtml.AppendLine(opt.ToString)
            Next
            dataList.InnerHtml = optionsHtml.ToString

            html.AppendLine(input.ToString)
            html.AppendLine(dataList.ToString)

            Return New HtmlString(html.ToString)
        End Function
    End Module
End Namespace

The HtmlHelper can then be used as follows:

VB.NET
@Imports MyProject.Mvc.HtmlHelpers

...

@Html.DataListInputFor(Function(m) m.CountryName, Model.GetCountries)

Where Model.GetCountries() could look like:

VB.NET
Public ReadOnly Property GetCountries() As IEnumerable(Of String)
    Get
        Return _db.Countries.Select(Function(c) c.Name)
    End Get
End Property

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)