Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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"); 
like image 246
paul Avatar asked Sep 24 '11 02:09

paul


2 Answers

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);     } } 
like image 118
John Landheer Avatar answered Sep 27 '22 22:09

John Landheer


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);         }      } } 
like image 45
Alexander Puchkov Avatar answered Sep 27 '22 21:09

Alexander Puchkov