Conditionally disable Html.DropDownList

How can I change this DropDownList declaration so that the disabled attribute is conditionally enabled / disabled?

<%= Html.DropDownList("Quantity", new SelectList(...), new{@disabled="disabled"} %> 

inoperative example:

 <%= Html.DropDownList("Quantity", new SelectList(...), new{@disabled=Model.CanEdit?"false":"disabled"} %> 

ps adding an if condition around the entire operator is not the desired approach :)

EDIT: based on this extension method from another question. I came up with the following extension:

 public static IDictionary<string, object> Disabled (this object obj, bool disabled) { return disabled ? obj.AddProperty ("disabled", "disabled") : obj.ToDictionary (); } 

which can then be used as

 <%= Html.DropDownList("Quantity", new SelectList(...), new{id="quantity"}.Disabled(Model.CanEdit) %> 
+15
asp.net-mvc
Jan 18 '10 at 21:48
source share
6 answers

Please do not write spaghetti code. There are Html helpers for this purpose:

 public static MvcHtmlString DropDownList(this HtmlHelper html, string name, SelectList values, bool canEdit) { if (canEdit) { return html.DropDownList(name, values); } return html.DropDownList(name, values, new { disabled = "disabled" }); } 

And then:

 <%= Html.DropDownList("Quantity", new SelectList(...), Model.CanEdit) %> 

Or maybe you could come up with something even better (if the model contains parameters):

 <%= Html.DropDownList("Quantity", Model) %> 

You will also receive a bonus to have a more uniform test code.

+19
Jan 18
source share

No need to add helper methods, you can just use

 <%= Html.DropDownList("Quantity", new SelectList(...), IsEditable == true ? new { @disabled = "disabled" } as object : new {} as object %> 

If you must delete the as object entries, this will not work, because by default new {} is a dynamic object compiled at runtime, so the two possible objects must have the same properties. But the Html attribute parameter is actually just an object, so this dynamics can be distinguished as objects to get around this.

This solution even allows the use of several HTML attributes, where one is optional and the other is not, i.e. class='whatever' is not optional, but disabled - this means that you put class='whatever' in both objects, but only one of them in the first place. Dimitrov’s answer does not support any user attributes other than disabled.

+22
Jun 03 '13 at 12:53 on
source share

One option is to create a custom version of Html.DropDownList that takes an additional parameter and does what you want ... but then you will need to create a new one for each type of helper - TextBoxFor, TextAreaFor, CheckBoxFor, etc ... and you still need to figure out how to make it work.

Instead, I decided to create an Html Helper to replace the usual anonymous HtmlAttributes object, as it will be compatible with all helpers that use HtmlAttributes without any special work. This solution also allows you to pass additional attributes like Class, Name or whatever. It does not block you only by disconnecting.

I created the following Helper - it accepts a logical and anonymous object. If the value is disabled, it adds the disabled attribute to the anonymous object (which is actually a Dictionary) with the value "disabled", otherwise it does not add the property at all.

 public static RouteValueDictionary ConditionalDisable( bool disabled, object htmlAttributes = null) { var dictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes); if (disabled) dictionary.Add("disabled", "disabled"); return dictionary; } 


An example of this in action:

 @Html.TextBoxFor(m => m.SomeProperty, HtmlHelpers.ConditionalDisable(true, new { @class = "someClass")) 


The huge advantage of this approach for me was that it works with almost all MVC HtmlHelpers, since they all have Overloads that accept RouteValueDictionary instead of an anonymous object.

Caution :
HtmlHelper.AnonymousObjectToHtmlAttributes () uses some ninja fancy code work to get things done. I'm not quite sure how effective it is ... but that was enough for what I use it for. Your mileage may vary.

I do not like this name, but I could not think of anything better. Renaming is easy.

I also do not like the syntax of use, but again I could not think of anything better. It should not be difficult to change. The extension method on object is one idea ... you will get new { @class = "someClass" }.ConditionalDisable(true) , but then if you only need the disable attribute and you have nothing more to add to what you something bigger, for example new {}.ConditionalDisable(true); and you also get an extension method that displays for all objects ... which is probably not desirable.

+5
Dec 17 '12 at 21:52
source share
 @bool IsEditable=true; @if (IsEditable) { Html.DropDownListFor(m => m, selectList); } else { Html.DropDownListFor(m => m, selectList, new { disabled = "disabled" }) } 
+2
Jul 18 '15 at 6:15
source share

Strongly typed version:

  public static MvcHtmlString DropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> html, Expression<Func<TModel, TProperty>> expression, IEnumerable<SelectListItem> selectList, string optionText, bool canEdit) { if (canEdit) { return html.DropDownListFor(expression, selectList, optionText); } return html.DropDownListFor(expression, selectList, optionText, new { disabled = "disabled" }); } 
0
Jan 24 '14 at 17:06
source share

I don't know if ASP.NET offers a more succinct special approach, but presumably you could do:

 <%= Html.DropDownList("Quantity", new SelectList(...), Model.CanEdit? new{@class="quantity"} : new{@class="quantity", @disabled:"disabled"}) %> 
-2
Jan 18 '10 at 21:53
source share



All Articles