Adding html class tag under <option> in Html.DropDownList
Asked Answered
A

7

39

I've been looking for answers on how to add an HTML class tag on my html.dropdownlist. here is the code

<%: Html.DropDownList("PackageId", new SelectList(ViewData["Packages"] as IEnumerable, "PackageId", "Name", Model.PackageId))%>

I want to add classes for options under the select element so that I can use this chained select :

<select id="category">
  <option value="1">One</option>
  <option value="2">Two</option>
</select>
<select id="package">
  <option value="1" class="1">One - package1</option>
  <option value="2" class="1">One - package2</option>
  <option value="3" class="2">Two - package1</option>
  <option value="4" class="2">Two - package2</option>
</select>

$("#series").chained("#mark");
Ailssa answered 24/9, 2011 at 2:37 Comment(1)
Does this answer your question? Razor DropDownListFor: Adding Extra Attribute To SelectList Option TagHolmquist
S
53

I've done this for the DropDownlistFor extension method, not the DropDownList you use, but you can probably figure that out yourself. This stuff is mostly copy/paste from the MVC sources. You can find the sources here.

public class ExtendedSelectListItem : SelectListItem
{
    public object htmlAttributes { get; set; }
}

public static partial class HtmlHelperExtensions
{
    public static MvcHtmlString ExtendedDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<ExtendedSelectListItem> selectList, string optionLabel, object htmlAttributes)
    {
        return SelectInternal(htmlHelper, optionLabel, ExpressionHelper.GetExpressionText(expression), selectList, false /* allowMultiple */, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
    }

    private static MvcHtmlString SelectInternal(this HtmlHelper htmlHelper, string optionLabel, string name, IEnumerable<ExtendedSelectListItem> selectList, bool allowMultiple, IDictionary<string, object> htmlAttributes)
    {
        string fullName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
        if (String.IsNullOrEmpty(fullName))
            throw new ArgumentException("No name");

        if (selectList == null)
            throw new ArgumentException("No selectlist");

        object defaultValue = (allowMultiple) ? GetModelStateValue(htmlHelper, fullName, typeof(string[])) : GetModelStateValue(htmlHelper, fullName, typeof(string));

        // If we haven't already used ViewData to get the entire list of items then we need to
        // use the ViewData-supplied value before using the parameter-supplied value.
        if (defaultValue == null)
            defaultValue = htmlHelper.ViewData.Eval(fullName);

        if (defaultValue != null)
        {
            IEnumerable defaultValues = (allowMultiple) ? defaultValue as IEnumerable : new[] { defaultValue };
            IEnumerable<string> values = from object value in defaultValues select Convert.ToString(value, CultureInfo.CurrentCulture);
            HashSet<string> selectedValues = new HashSet<string>(values, StringComparer.OrdinalIgnoreCase);
            List<ExtendedSelectListItem> newSelectList = new List<ExtendedSelectListItem>();

            foreach (ExtendedSelectListItem item in selectList)
            {
                item.Selected = (item.Value != null) ? selectedValues.Contains(item.Value) : selectedValues.Contains(item.Text);
                newSelectList.Add(item);
            }
            selectList = newSelectList;
        }

        // Convert each ListItem to an <option> tag
        StringBuilder listItemBuilder = new StringBuilder();

        // Make optionLabel the first item that gets rendered.
        if (optionLabel != null)
            listItemBuilder.Append(ListItemToOption(new ExtendedSelectListItem() { Text = optionLabel, Value = String.Empty, Selected = false }));

        foreach (ExtendedSelectListItem item in selectList)
        {
            listItemBuilder.Append(ListItemToOption(item));
        }

        TagBuilder tagBuilder = new TagBuilder("select")
        {
            InnerHtml = listItemBuilder.ToString()
        };
        tagBuilder.MergeAttributes(htmlAttributes);
        tagBuilder.MergeAttribute("name", fullName, true /* replaceExisting */);
        tagBuilder.GenerateId(fullName);
        if (allowMultiple)
            tagBuilder.MergeAttribute("multiple", "multiple");

        // If there are any errors for a named field, we add the css attribute.
        ModelState modelState;
        if (htmlHelper.ViewData.ModelState.TryGetValue(fullName, out modelState))
        {
            if (modelState.Errors.Count > 0)
            {
                tagBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName);
            }
        }

        tagBuilder.MergeAttributes(htmlHelper.GetUnobtrusiveValidationAttributes(name));

        return MvcHtmlString.Create(tagBuilder.ToString(TagRenderMode.Normal));
    }

    internal static string ListItemToOption(ExtendedSelectListItem item)
    {
        TagBuilder builder = new TagBuilder("option")
        {
            InnerHtml = HttpUtility.HtmlEncode(item.Text)
        };
        if (item.Value != null)
        {
            builder.Attributes["value"] = item.Value;
        }
        if (item.Selected)
        {
            builder.Attributes["selected"] = "selected";
        }
        builder.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(item.htmlAttributes));
        return builder.ToString(TagRenderMode.Normal);
    }
}
Sapienza answered 24/9, 2011 at 7:13 Comment(10)
This was really good, apart from it is missing the GetModelStateValue() method which is (now?) internal. This is covered by this question: #6967648Savino
Here's the corrected line: object defaultValue = (allowMultiple) ? htmlHelper.GetModelStateValue(fullName, typeof(string[])) : htmlHelper.GetModelStateValue(fullName, typeof(string));Mcsweeney
I ended up taking the same approach so that I could get the "title" attribute of an html select set. This allows you to show more information on hover (granted, probably not that useful in mobile).Laurence
This is awesome! I have build entire DropDown cascade with jquery with this approach.Harker
For those having problem with GetModelStateValue(), using method definition of GetModelStateValue() inside this code shared on Github (just copy paste to HtmlHelperExtensions) solves the issue:Eleven41.Web.Mvc.Bootstrap GithubLutz
Thank you. I modified this to work for a DropDownList variant so that I could plug it into the Telerik grid and it's working wonderfully.Sell
Can anyone show an example of the Razor code that is needed to use the extension?Signification
very interesting to see it like TagHelperAcetal
The solution for the GetModelStateValue() commented by @Lutz is deprecated. The repository where the link refers might be removed.Emylee
Question is asked 8 years ago and my answer is 5, many things have changed since then. Still, if one wishes to see that code I linked, you can find it here in new location: Eleven41.Web.Mvc.BootstrapLutz
E
16

Here's a little improved version of @john-landheer's solution.

Things improved:

  • problem with GetModelStateValue() fixed
  • DropDownList() extension method added
  • unobtrusive validation attributes will be rendered just like they should

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Linq;
    using System.Linq.Expressions;
    using System.Text;
    using System.Web;
    using System.Web.Mvc;
    
    namespace App.Infrastructure.Helpers
    {
        public class ExtendedSelectListItem : SelectListItem
        {
            public object HtmlAttributes { get; set; }
        }
    
        public static class ExtendedSelectExtensions
        {
            internal static object GetModelStateValue(this HtmlHelper htmlHelper, string key, Type destinationType)
            {
                System.Web.Mvc.ModelState modelState;
                if (htmlHelper.ViewData.ModelState.TryGetValue(key, out modelState))
                {
                    if (modelState.Value != null)
                    {
                        return modelState.Value.ConvertTo(destinationType, null /* culture */);
                    }
                }
                return null;
            }
    
            public static MvcHtmlString ExtendedDropDownList(this HtmlHelper htmlHelper, string name, IEnumerable<ExtendedSelectListItem> selectList)
            {
                return ExtendedDropDownList(htmlHelper, name, selectList, (string)null, (IDictionary<string, object>)null);
            }
    
            public static MvcHtmlString ExtendedDropDownList(this HtmlHelper htmlHelper, string name, IEnumerable<ExtendedSelectListItem> selectList, string optionLabel, IDictionary<string, object> htmlAttributes)
            {
                return ExtendedDropDownListHelper(htmlHelper, null, name, selectList, optionLabel, htmlAttributes);
            }
    
            public static MvcHtmlString ExtendedDropDownListHelper(this HtmlHelper htmlHelper, ModelMetadata metadata, string expression, IEnumerable<ExtendedSelectListItem> selectList, string optionLabel, IDictionary<string, object> htmlAttributes)
            {
                return SelectInternal(htmlHelper, metadata, optionLabel, expression, selectList, false, htmlAttributes);
            }
    
            public static MvcHtmlString ExtendedDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper,
                Expression<Func<TModel, TProperty>> expression, IEnumerable<ExtendedSelectListItem> selectList,
                string optionLabel, object htmlAttributes)
            {
                if (expression == null)
                    throw new ArgumentNullException("expression");
                ModelMetadata metadata = ModelMetadata.FromLambdaExpression<TModel, TProperty>(expression, htmlHelper.ViewData);
                return SelectInternal(htmlHelper, metadata, optionLabel, ExpressionHelper.GetExpressionText(expression), selectList,
                    false /* allowMultiple */, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
            }
    
            private static MvcHtmlString SelectInternal(this HtmlHelper htmlHelper, ModelMetadata metadata, string optionLabel, string name,
                IEnumerable<ExtendedSelectListItem> selectList, bool allowMultiple,
                IDictionary<string, object> htmlAttributes)
            {
                string fullName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
                if (String.IsNullOrEmpty(fullName))
                    throw new ArgumentException("No name");
    
                if (selectList == null)
                    throw new ArgumentException("No selectlist");
    
                object defaultValue = (allowMultiple)
                    ? htmlHelper.GetModelStateValue(fullName, typeof(string[]))
                    : htmlHelper.GetModelStateValue(fullName, typeof(string));
    
                // If we haven't already used ViewData to get the entire list of items then we need to
                // use the ViewData-supplied value before using the parameter-supplied value.
                if (defaultValue == null)
                    defaultValue = htmlHelper.ViewData.Eval(fullName);
    
                if (defaultValue != null)
                {
                    IEnumerable defaultValues = (allowMultiple) ? defaultValue as IEnumerable : new[] { defaultValue };
                    IEnumerable<string> values = from object value in defaultValues
                                                 select Convert.ToString(value, CultureInfo.CurrentCulture);
                    HashSet<string> selectedValues = new HashSet<string>(values, StringComparer.OrdinalIgnoreCase);
                    List<ExtendedSelectListItem> newSelectList = new List<ExtendedSelectListItem>();
    
                    foreach (ExtendedSelectListItem item in selectList)
                    {
                        item.Selected = (item.Value != null)
                            ? selectedValues.Contains(item.Value)
                            : selectedValues.Contains(item.Text);
                        newSelectList.Add(item);
                    }
                    selectList = newSelectList;
                }
    
                // Convert each ListItem to an <option> tag
                StringBuilder listItemBuilder = new StringBuilder();
    
                // Make optionLabel the first item that gets rendered.
                if (optionLabel != null)
                    listItemBuilder.Append(
                        ListItemToOption(new ExtendedSelectListItem()
                        {
                            Text = optionLabel,
                            Value = String.Empty,
                            Selected = false
                        }));
    
                foreach (ExtendedSelectListItem item in selectList)
                {
                    listItemBuilder.Append(ListItemToOption(item));
                }
    
                TagBuilder tagBuilder = new TagBuilder("select")
                {
                    InnerHtml = listItemBuilder.ToString()
                };
                tagBuilder.MergeAttributes(htmlAttributes);
                tagBuilder.MergeAttribute("name", fullName, true /* replaceExisting */);
                tagBuilder.GenerateId(fullName);
                if (allowMultiple)
                    tagBuilder.MergeAttribute("multiple", "multiple");
    
                // If there are any errors for a named field, we add the css attribute.
                System.Web.Mvc.ModelState modelState;
                if (htmlHelper.ViewData.ModelState.TryGetValue(fullName, out modelState))
                {
                    if (modelState.Errors.Count > 0)
                    {
                        tagBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName);
                    }
                }
    
                tagBuilder.MergeAttributes(htmlHelper.GetUnobtrusiveValidationAttributes(fullName, metadata));
    
                return MvcHtmlString.Create(tagBuilder.ToString(TagRenderMode.Normal));
            }
    
            internal static string ListItemToOption(ExtendedSelectListItem item)
            {
                TagBuilder builder = new TagBuilder("option")
                {
                    InnerHtml = HttpUtility.HtmlEncode(item.Text)
                };
                if (item.Value != null)
                {
                    builder.Attributes["value"] = item.Value;
                }
                if (item.Selected)
                {
                    builder.Attributes["selected"] = "selected";
                }
                builder.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(item.HtmlAttributes));
                return builder.ToString(TagRenderMode.Normal);
            }
    
        }
    }
    
Elegancy answered 4/12, 2015 at 20:32 Comment(3)
Great! I've tried to translate to vb.net and there's a warning: Variable 'modelState' is passed by reference before it has been assigned a value. A null reference exception could result at runtime. Does this have any effect?Horseshoe
If anyone is using this helper within a loop, and you're using an older version of MVC framework (e.g. 3, 4), be aware there was a MVC bug preventing an existing (pre-selected, like on an Edit page load scenario) value to be marked correctly (i.e. the selected="selected" attribute was missing for that value's option element). See my answer here.Roswald
Heads up from 2020, if using this with collection items, you will need to use name and not fullname into htmlHelper.GetModelStateValue, that way you don't get the appended GUID in the name. Also, in order for default (pre-selected) values to work, you will also need to use reflection in the htmlHelper.GetModelStateValue function like this, since the values are not yet in the ModelState: else if (htmlHelper.ViewData.Model != null) { return htmlHelper.ViewData.Model.GetType().GetProperty(key).GetValue(htmlHelper.ViewData.Model, null);}Pretentious
D
6

This is not possible with the DropDownList helper that is built into ASP.NET MVC. As a consequence you will have to write your own helper if you need to do that. You could take a look at the source code of ASP.NET MVC which uses TagBuilder to generate the options and you could append any attributes in your custom implementation. Another less elegant solution is to manually loop through the dataset in the view and generate individual option elements.

Dombrowski answered 24/9, 2011 at 6:29 Comment(1)
Any idea if this has been covered in newer version of framework (5.2.3) ? It's lame that you have to write custom code to achieve pretty common use behavior :(Londoner
A
2

First thing that comes to my mind is JQuery here. You can do this with following code easily :

$("#bla").find("option").addClass("poo");
Armalla answered 24/9, 2011 at 3:21 Comment(7)
i cant do that. i need the class to change values for my chained select.Ailssa
@Ailssa Ok, but this doesn't mean it won't work. put the above code before your necessary JQuery code then the classes will be set before you need them.Armalla
I just want to add that i think this is a quick and neat approach. The default html helpers a fine in MVC and adding classes via jquery is quick. Yeah this might stuff up in non js browsers but .... who nowadays has js disabled ? 1.5% of the population that is who.Botswana
@gerdi if you have JS disabled browser, you don't deserve to browse :)Armalla
This is exponentially simpler than writing an extension method. And isn't that the point in using a view engine in the first place? This not only worked, but I believe it does solve @Ailssa 's concern. As long as it is inside $(document).ready(function() {}), that class selector will be available at any point after the document is done loading/rendering those dom objects.Consubstantiate
There is a problem with this approach if the stuff you want to decorate each option with comes from Model data .. that doesn't live on the page,unless you add it to the page elsewhere (ie, JSON), in which case you'd likely just get it from that location instead of adding to the options.Generalship
@arkade Tin-hatters, that's who. And who needs them, anyway? They smell like onions.Chibouk
G
1

A simple solution : When you add

@Html.DropDownList("someID", new SelectList(Model.selectItems),"--Select--",new { @class= "select-ddl" })

Add one more class in your css as

.select-ddl option {}

This class will be applied to all your option tags in HTML.

Giveaway answered 2/2, 2020 at 12:30 Comment(0)
S
0

I wrote a wrapper that simply modifies the html:

    public static MvcHtmlString DisableFirstItem(MvcHtmlString htmlString)
    {
        return new MvcHtmlString(
            htmlString.ToString()
            .Replace("<option value=\"Unknown\">", 
                     "<option disabled value=\"Unknown\">")
        );
    }

and then I wrapped my DropDownListFor with this helper function:

        @Html.Raw(MyHtmlHelpers.DisableFirstItem(

          Html.DropDownListFor(m => m.Instrument,
            new SelectList(ReflectionHelpers.GenerateEnumDictionary<OrderInstrument>(true), "Key", "Value", Model.Instrument),
            new { @class = "form-control" })

        ))

You could obviously make the helper function more sophisticated if you want.

Seraphine answered 23/10, 2015 at 17:0 Comment(0)
L
0

I modified @Alexander Puchkov answer in order to automatically create an ExtendedSelectList that contains a collection of ExtendedSelectListItems that is automatically generated from the properties of the Items being passed into it without having to specify the attributes for each SelectListItem manually. It creates the attributes as "data-*". You can exclude some properties using the function parms or by having them listed in excludedProperties.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Web.UI;

namespace App.Infrastructure.Helpers.Extensions
{
    public class ExtendedSelectList : SelectList
    {
        static readonly string[] excludedProperties = new string[] { "DateInsert", "DateUpdate" }; // Write here properties you want to exclude for every ExtendedSelectList
        public ICollection<ExtendedSelectListItem> ExtendedSelectListItems { get; set; }
        public ExtendedSelectList(IEnumerable items, string dataValueField, string dataTextField, object selectedValue, params string[] exclude) : base(items, dataValueField, dataTextField, selectedValue)
        {
            ExtendedSelectListItems = new List<ExtendedSelectListItem>();
            exclude = exclude.Concat(new string[] { dataValueField, dataTextField }).ToArray();
            exclude = exclude.Concat(excludedProperties).ToArray();
            foreach (var selectListItem in this.AsEnumerable())
            {
                var extendedItem = new ExtendedSelectListItem() { Value = selectListItem.Value, Text = selectListItem.Text, Selected = selectListItem.Selected, Disabled = selectListItem.Disabled, Group = selectListItem.Group };
                var htmlAttributes = new Dictionary<string, object>();
                var item = items.Cast<object>().FirstOrDefault(x =>
                {
                    string valueItem = DataBinder.Eval(x, DataValueField).ToString();
                    string valueSelectListItem = DataBinder.Eval(selectListItem, "Value").ToString();
                    return valueItem == valueSelectListItem;
                });
                foreach (PropertyInfo property in item.GetType().GetProperties())
                {
                    if (!property.CanRead || (property.GetIndexParameters().Length > 0) || (exclude != null && exclude.Contains(property.Name)))
                        continue;

                    htmlAttributes.Add("data-" + property.Name.ToLower(), property.GetValue(item));
                }
                extendedItem.HtmlAttributesDict = htmlAttributes;
                ExtendedSelectListItems.Add(extendedItem);
            }
        }
    }
    public class ExtendedSelectListItem : SelectListItem
    {
        public object HtmlAttributes { get; set; }
        public Dictionary<string, object> HtmlAttributesDict { get; set; }
    }

    public static class ExtendedSelectExtensions
    {
        internal static object GetModelStateValue(this HtmlHelper htmlHelper, string key, Type destinationType)
        {
            System.Web.Mvc.ModelState modelState;
            if (htmlHelper.ViewData.ModelState.TryGetValue(key, out modelState))
            {
                if (modelState.Value != null)
                {
                    return modelState.Value.ConvertTo(destinationType, null /* culture */);
                }
            }
            return null;
        }

        public static MvcHtmlString ExtendedDropDownList(this HtmlHelper htmlHelper, string name, IEnumerable<ExtendedSelectListItem> selectList)
        {
            return ExtendedDropDownList(htmlHelper, name, selectList, (string)null, (IDictionary<string, object>)null);
        }

        public static MvcHtmlString ExtendedDropDownList(this HtmlHelper htmlHelper, string name, IEnumerable<ExtendedSelectListItem> selectList, string optionLabel, IDictionary<string, object> htmlAttributes)
        {
            return ExtendedDropDownListHelper(htmlHelper, null, name, selectList, optionLabel, htmlAttributes);
        }

        public static MvcHtmlString ExtendedDropDownListHelper(this HtmlHelper htmlHelper, ModelMetadata metadata, string expression, IEnumerable<ExtendedSelectListItem> selectList, string optionLabel, IDictionary<string, object> htmlAttributes)
        {
            return SelectInternal(htmlHelper, metadata, optionLabel, expression, selectList, false, htmlAttributes);
        }

        public static MvcHtmlString ExtendedDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper,
            Expression<Func<TModel, TProperty>> expression, IEnumerable<ExtendedSelectListItem> selectList,
            string optionLabel, object htmlAttributes)
        {
            if (expression == null)
                throw new ArgumentNullException("expression");
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression<TModel, TProperty>(expression, htmlHelper.ViewData);
            return SelectInternal(htmlHelper, metadata, optionLabel, ExpressionHelper.GetExpressionText(expression), selectList,
                false /* allowMultiple */, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
        }

        private static MvcHtmlString SelectInternal(this HtmlHelper htmlHelper, ModelMetadata metadata, string optionLabel, string name,
            IEnumerable<ExtendedSelectListItem> selectList, bool allowMultiple,
            IDictionary<string, object> htmlAttributes)
        {
            string fullName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
            if (String.IsNullOrEmpty(fullName))
                throw new ArgumentException("No name");

            if (selectList == null)
                throw new ArgumentException("No selectlist");

            object defaultValue = (allowMultiple)
                ? htmlHelper.GetModelStateValue(fullName, typeof(string[]))
                : htmlHelper.GetModelStateValue(fullName, typeof(string));

            // If we haven't already used ViewData to get the entire list of items then we need to
            // use the ViewData-supplied value before using the parameter-supplied value.
            if (defaultValue == null)
                defaultValue = htmlHelper.ViewData.Eval(fullName);

            if (defaultValue != null)
            {
                IEnumerable defaultValues = (allowMultiple) ? defaultValue as IEnumerable : new[] { defaultValue };
                IEnumerable<string> values = from object value in defaultValues
                                             select Convert.ToString(value, CultureInfo.CurrentCulture);
                HashSet<string> selectedValues = new HashSet<string>(values, StringComparer.OrdinalIgnoreCase);
                List<ExtendedSelectListItem> newSelectList = new List<ExtendedSelectListItem>();

                foreach (ExtendedSelectListItem item in selectList)
                {
                    item.Selected = (item.Value != null)
                        ? selectedValues.Contains(item.Value)
                        : selectedValues.Contains(item.Text);
                    newSelectList.Add(item);
                }
                selectList = newSelectList;
            }

            // Convert each ListItem to an <option> tag
            StringBuilder listItemBuilder = new StringBuilder();

            // Make optionLabel the first item that gets rendered.
            if (optionLabel != null)
                listItemBuilder.Append(
                    ListItemToOption(new ExtendedSelectListItem()
                    {
                        Text = optionLabel,
                        Value = String.Empty,
                        Selected = false
                    }));

            foreach (ExtendedSelectListItem item in selectList)
            {
                listItemBuilder.Append(ListItemToOption(item));
            }

            TagBuilder tagBuilder = new TagBuilder("select")
            {
                InnerHtml = listItemBuilder.ToString()
            };
            tagBuilder.MergeAttributes(htmlAttributes);
            tagBuilder.MergeAttribute("name", fullName, true /* replaceExisting */);
            tagBuilder.GenerateId(fullName);
            if (allowMultiple)
                tagBuilder.MergeAttribute("multiple", "multiple");

            // If there are any errors for a named field, we add the css attribute.
            System.Web.Mvc.ModelState modelState;
            if (htmlHelper.ViewData.ModelState.TryGetValue(fullName, out modelState))
            {
                if (modelState.Errors.Count > 0)
                {
                    tagBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName);
                }
            }

            tagBuilder.MergeAttributes(htmlHelper.GetUnobtrusiveValidationAttributes(fullName, metadata));

            return MvcHtmlString.Create(tagBuilder.ToString(TagRenderMode.Normal));
        }

        internal static string ListItemToOption(ExtendedSelectListItem item)
        {
            TagBuilder builder = new TagBuilder("option")
            {
                InnerHtml = HttpUtility.HtmlEncode(item.Text)
            };
            if (item.Value != null)
            {
                builder.Attributes["value"] = item.Value;
            }
            if (item.Selected)
            {
                builder.Attributes["selected"] = "selected";
            }
            var attributes = HtmlHelper.AnonymousObjectToHtmlAttributes(item.HtmlAttributes);
            builder.MergeAttributes(attributes);
            if (item.HtmlAttributesDict != null)
            {
                foreach (var attribute in item.HtmlAttributesDict)
                {
                    var key = attribute.Key.ToLower(); // We call ToLower to keep the same naming convention used by MVC's HtmlHelper.AnonymousObjectToHtmlAttributes
                    var value = attribute.Value?.ToString() ?? "";
                    builder.Attributes[key] = value;
                }
            }
            return builder.ToString(TagRenderMode.Normal);
        }

    }
}

To use it in Razor you do:

@{
    var availableLocations = new ExtendedSelectList(Model.AvailableLocations, "Id", "Value", Model.LocationId);
}
@Html.ExtendedDropDownListFor(m => Model.LocationId, availableLocations.ExtendedSelectListItems, null, new { id = "ddLocation" })

Notice the "availableLocations.ExtendedSelectListItems" because you can't use the Enumerable items directly as they are simple SelectListItem

Ligneous answered 30/7, 2020 at 8:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.