views:

191

answers:

2

I'm not seeing a way to create, via the HtmlHelper, a SelectListItem that will spit out the following HTML:

<option disabled="disabled">don't click this</option>

The only properties SelectListItem has are:

new SelectListItem{
  Name = "don't click this",
  Value = string.Empty,
  Selected = false
}

The only option I see is to

  1. Subclass the SelectListItem to add an Enabled property to get the value to the view
  2. Not use the HTML helper for DropDownList
  3. Create a new HtmlHelper extension that accepts my new EnablableSelectList and adds my disabled attribute.
A: 

If all you are trying to do is prevent a user from selecting a certain value from the list, it seems like the simpler and more time-efficient way to do it is to use input validation. Which you may quite possibly be doing anyways, if you want to verify they've made a selection to begin with.

Thyamine
I already have input validation that invalidates the selection, but all other browsers, besides IE, will not let you select the item at all if the `disabled="disabled"` attribute is present.
Mark
Going forward IE 8 will support it, or does support it. For IE 6 and 7 I would agree that you'd have to try and create your own Item, but I'm not certain the best approach there. Again, I would look at how long it would take to work on that, and see if it's worth the time spent troubleshooting it given what browsers/version users will be using.
Thyamine
Actually, IE7 does obey the `disabled="disabled"`. I must retract all my disdain for IE....on this issue. I'm just really surprised the `Enabled` attribute was left off the `SelectListItem`.
Mark
+2  A: 

This is something I might try before recreating the helper completely. The basic idea is that the Html you get from the helper should be well formed, so it should be safe to parse. So you can build on that idea by making your own extension that uses the existing extension but adds the functionality to disable the items.

Something like this might do (totally untested)

public class CustomSelectItem : SelectListItem
{
    public bool Enabled { get; set; }
}

public static class CustomHtmlHelpers
{
    public static MvcHtmlString MyDropDownList(this HtmlHelper html, IEnumerable<CustomSelectItem> selectList)
    {
        var selectDoc = XDocument.Parse(html.DropDownList("", (IEnumerable<SelectListItem>)selectList).ToString());

        var options = from XElement el in selectDoc.Element("select").Descendants()
                                    select el;

        foreach (var item in options)
        {
            var itemValue = item.Attribute("value");
            if (!selectList.Where(x => x.Value == itemValue.Value).Single().Enabled)
                item.SetAttributeValue("disabled", "disabled");
        }

        // rebuild the control, resetting the options with the ones you modified
        selectDoc.Root.ReplaceAll(options.ToArray());
        return MvcHtmlString.Create(selectDoc.ToString());
    }
}
Jab
+1 That's definitely lighter than recreating the entire helper extension; however, if I was going to recreate it, I would probably just steal the source for the Helper Extension and tweak it a bit.
Mark