Chcę ustawić wyłączenie atrybutu na podstawie warunku dla Html.TextBoxFor w asp.net MVC, jak poniżej
@Html.TextBoxFor(model => model.ExpireDate, new { style = "width: 70px;", maxlength = "10", id = "expire-date" disabled = (Model.ExpireDate == null ? "disable" : "") })
Ten pomocnik ma dwa wyjścia wyłączone = „wyłączone” lub wyłączone = „”. oba motywy powodują wyłączenie pola tekstowego.
Chcę wyłączyć pole tekstowe, jeśli Model.ExpireDate == null w przeciwnym razie chcę je włączyć
asp.net-mvc
asp.net-mvc-3
razor
html-helper
Ghooti Farangi
źródło
źródło
Odpowiedzi:
Prawidłowy sposób to:
disabled="disabled"
Przeglądarki również mogą to zaakceptować,
disabled=""
ale polecam pierwsze podejście.Mając to na uwadze, zalecałbym napisanie niestandardowego pomocnika HTML w celu hermetyzacji tej funkcji wyłączającej w fragment kodu wielokrotnego użytku:
using System; using System.Linq.Expressions; using System.Web; using System.Web.Mvc; using System.Web.Mvc.Html; using System.Web.Routing; public static class HtmlExtensions { public static IHtmlString MyTextBoxFor<TModel, TProperty>( this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes, bool disabled ) { var attributes = new RouteValueDictionary(htmlAttributes); if (disabled) { attributes["disabled"] = "disabled"; } return htmlHelper.TextBoxFor(expression, attributes); } }
którego możesz użyć w ten sposób:
@Html.MyTextBoxFor( model => model.ExpireDate, new { style = "width: 70px;", maxlength = "10", id = "expire-date" }, Model.ExpireDate == null )
i możesz wnieść jeszcze więcej inteligencji do tego pomocnika:
public static class HtmlExtensions { public static IHtmlString MyTextBoxFor<TModel, TProperty>( this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes ) { var attributes = new RouteValueDictionary(htmlAttributes); var metaData = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData); if (metaData.Model == null) { attributes["disabled"] = "disabled"; } return htmlHelper.TextBoxFor(expression, attributes); } }
dzięki czemu nie musisz już określać warunku wyłączenia:
@Html.MyTextBoxFor( model => model.ExpireDate, new { style = "width: 70px;", maxlength = "10", id = "expire-date" } )
źródło
W rzeczywistości wewnętrzne zachowanie polega na tłumaczeniu anonimowego obiektu na słownik. Więc to, co robię w tych scenariuszach, to szukanie słownika:
@{ var htmlAttributes = new Dictionary<string, object> { { "class" , "form-control"}, { "placeholder", "Why?" } }; if (Model.IsDisabled) { htmlAttributes.Add("disabled", "disabled"); } } @Html.EditorFor(m => m.Description, new { htmlAttributes = htmlAttributes })
Albo, jak Stephen skomentował tutaj :
@Html.EditorFor(m => m.Description, Model.IsDisabled ? (object)new { disabled = "disabled" } : (object)new { })
źródło
Podoba mi się metoda Darina. Ale szybki sposób rozwiązania tego problemu,
Html.TextBox("Expiry", null, new { style = "width: 70px;", maxlength = "10", id = "expire-date", disabled = "disabled" }).ToString().Replace("disabled=\"disabled\"", (1 == 2 ? "" : "disabled=\"disabled\""))
źródło
Jednym prostym podejściem, które zastosowałem, jest renderowanie warunkowe:
@(Model.ExpireDate == null ? @Html.TextBoxFor(m => m.ExpireDate, new { @disabled = "disabled" }) : @Html.TextBoxFor(m => m.ExpireDate) )
źródło
Jeśli nie używasz pomocników html, możesz użyć prostego wyrażenia trójskładnikowego w następujący sposób:
<input name="Field" value="@Model.Field" tabindex="0" @(Model.IsDisabledField ? "disabled=\"disabled\"" : "")>
źródło
Osiągnąłem to za pomocą kilku metod rozszerzających
private const string endFieldPattern = "^(.*?)>"; public static MvcHtmlString IsDisabled(this MvcHtmlString htmlString, bool disabled) { string rawString = htmlString.ToString(); if (disabled) { rawString = Regex.Replace(rawString, endFieldPattern, "$1 disabled=\"disabled\">"); } return new MvcHtmlString(rawString); } public static MvcHtmlString IsReadonly(this MvcHtmlString htmlString, bool @readonly) { string rawString = htmlString.ToString(); if (@readonly) { rawString = Regex.Replace(rawString, endFieldPattern, "$1 readonly=\"readonly\">"); } return new MvcHtmlString(rawString); }
i wtedy....
@Html.TextBoxFor(model => model.Name, new { @class= "someclass"}).IsDisabled(Model.ExpireDate == null)
źródło
To późno, ale niektórym osobom może się przydać.
Rozszerzyłem odpowiedź @ DarinDimitrov, aby umożliwić przekazanie drugiego obiektu, który przyjmuje dowolną liczbę logicznych atrybutów html, takich jak
disabled="disabled" checked="checked", selected="selected"
itp.Wyrenderuje atrybut tylko wtedy, gdy wartość właściwości jest prawdziwa, cokolwiek innego i atrybut nie zostanie w ogóle renderowany.
Niestandardowy HtmlHelper do ponownego wykorzystania:
public static class HtmlExtensions { public static IHtmlString MyTextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes, object booleanHtmlAttributes) { var attributes = new RouteValueDictionary(htmlAttributes); //Reflect over the properties of the newly added booleanHtmlAttributes object foreach (var prop in booleanHtmlAttributes.GetType().GetProperties()) { //Find only the properties that are true and inject into the main attributes. //and discard the rest. if (ValueIsTrue(prop.GetValue(booleanHtmlAttributes, null))) { attributes[prop.Name] = prop.Name; } } return htmlHelper.TextBoxFor(expression, attributes); } private static bool ValueIsTrue(object obj) { bool res = false; try { res = Convert.ToBoolean(obj); } catch (FormatException) { res = false; } catch(InvalidCastException) { res = false; } return res; } }
Którego możesz użyć w ten sposób:
@Html.MyTextBoxFor(m => Model.Employee.Name , new { @class = "x-large" , placeholder = "Type something…" } , new { disabled = true})
źródło
Jest rozwiązany za pomocą RouteValueDictionary (działa dobrze jako htmlAttributes, ponieważ jest oparty na IDictionary) i metody rozszerzenia:
public static RouteValueDictionary AddIf(this RouteValueDictionary dict, bool condition, string name, object value) { if (condition) dict.Add(name, value); return dict; }
Stosowanie:
@Html.TextBoxFor(m => m.GovId, new RouteValueDictionary(new { @class = "form-control" }) .AddIf(Model.IsEntityFieldsLocked, "disabled", "disabled"))
Kredyt trafia do https://stackoverflow.com/a/3481969/40939
źródło
jeśli nie chcesz używać pomocników HTML, spójrz na moje rozwiązanie
disabled="@(your Expression that returns true or false")"
że to
@{ bool isManager = (Session["User"] as User).IsManager; } <textarea rows="4" name="LetterManagerNotes" disabled="@(!isManager)"></textarea>
i myślę, że lepszym sposobem na zrobienie tego jest sprawdzenie kontrolera i zapisanie go w zmiennej dostępnej w widoku (silnik Razor), aby
the view free from business logic
źródło
Jeszcze innym rozwiązaniem byłoby utworzenie
Dictionary<string, object>
przed wywołaniemTextBoxFor
i przekazanie tego słownika. W słowniku dodaj"disabled"
klucz tylko wtedy, gdy pole tekstowe ma być wyłączone. Nie jest to najładniejsze rozwiązanie, ale proste i nieskomplikowane.źródło
Innym podejściem jest wyłączenie pola tekstowego po stronie klienta.
W twoim przypadku masz tylko jedno pole tekstowe, które musisz wyłączyć, ale rozważ przypadek, w którym masz wiele pól wejściowych, zaznaczania i pól tekstowych, których nie musisz wyłączać.
Dużo łatwiej jest to zrobić za pomocą jquery + (ponieważ nie możemy polegać na danych pochodzących od klienta) dodaj trochę logiki do kontrolera, aby zapobiec zapisywaniu tych pól.
Oto przykład:
<input id="document_Status" name="document.Status" type="hidden" value="2" /> $(document).ready(function () { disableAll(); } function disableAll() { var status = $('#document_Status').val(); if (status != 0) { $("input").attr('disabled', true); $("textarea").attr('disabled', true); $("select").attr('disabled', true); } }
źródło
Podoba mi się podejście oparte na metodzie rozszerzenia, więc nie musisz przechodzić przez wszystkie możliwe parametry.
Jednak używanie wyrażeń regularnych może być dość trudne (i nieco wolniejsze), więc
XDocument
zamiast tego użyłem :public static MvcHtmlString SetDisabled(this MvcHtmlString html, bool isDisabled) { var xDocument = XDocument.Parse(html.ToHtmlString()); if (!(xDocument.FirstNode is XElement element)) { return html; } element.SetAttributeValue("disabled", isDisabled ? "disabled" : null); return MvcHtmlString.Create(element.ToString()); }
Użyj następującej metody rozszerzenia:
@Html.EditorFor(m => m.MyProperty).SetDisabled(Model.ExpireDate == null)
źródło