Html.TextBoxFor에 대한 조건에 따라 비활성화 속성 설정


81

asp.net MVC에서 Html.TextBoxFor에 대한 조건에 따라 비활성화 속성을 설정하고 싶습니다.

@Html.TextBoxFor(model => model.ExpireDate, new { style = "width: 70px;", maxlength = "10", id = "expire-date" disabled = (Model.ExpireDate == null ? "disable" : "") })

이 도우미에는 두 개의 출력이 disabled = "disabled"또는 disabled = ""입니다. 두 테마 모두 텍스트 상자를 비활성화합니다.

Model.ExpireDate == null이면 텍스트 상자를 비활성화하고 싶습니다. 그렇지 않으면 활성화하고 싶습니다.


여기에 내 대답에서보세요 : stackoverflow.com/a/43131930/6680521
Extragorey

답변:


85

유효한 방법은 다음과 같습니다.

disabled="disabled"

브라우저도 받아 들일 수 disabled="" 있지만 첫 번째 방법을 권장합니다.

이제이 비활성화 기능을 재사용 가능한 코드 조각으로 캡슐화하기 위해 사용자 정의 HTML 도우미를 작성하는 것이 좋습니다 .

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);
    }
}

다음과 같이 사용할 수 있습니다.

@Html.MyTextBoxFor(
    model => model.ExpireDate, 
    new { 
        style = "width: 70px;", 
        maxlength = "10", 
        id = "expire-date" 
    }, 
    Model.ExpireDate == null
)

이 도우미에 더 많은 지능 을 가져올 수 있습니다 .

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);
    }
}

이제 더 이상 비활성화 된 조건을 지정할 필요가 없습니다.

@Html.MyTextBoxFor(
    model => model.ExpireDate, 
    new { 
        style = "width: 70px;", 
        maxlength = "10", 
        id = "expire-date" 
    }
)

나는 그것을 사용하려는 다른 Model.ExpireDate == null의 경우, 텍스트 상자를 비활성화 할
Ghooti Farangi

4
이 솔루션은 훌륭합니다.하지만 우리가 사용하는 모든 HtmlHelper 주위에 래퍼를 둘 필요가없고 비활성화 된 속성 (TextBoxFor, TextAreaFor, CheckBoxFor 등)을 가질 필요가없는 깨끗한 솔루션을 찾는 것이 좋습니다. .) 이상적으로는 기존의 것과 인라인으로 작동하는 것. 기본적으로 익명 개체를 래핑하고 RouteValueDictionary를 반환하는 솔루션을 만들었지 만 특별히 깔끔하게 느껴지지는 않습니다.
미르

3
"disabled", "disabled = ''"및 "disabled = 'disabled'"는 모두 html에서 똑같이 유효하며 더 짧은 것을 다른 브라우저 에서만 허용 할 수 있다고 말하는 것은 오해의 소지가 있습니다 (그리고 거짓) . Cf. dev.w3.org/html5/markup/syntax.html#syntax-attr-empty
Shautieh 2013-09-24

53

실제로 내부 동작은 익명 객체를 사전으로 변환합니다. 그래서이 시나리오에서 제가하는 일은 사전을 찾는 것입니다.

@{
  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 })

또는 Stephen이 여기에 언급 했듯이 :

@Html.EditorFor(m => m.Description,
    Model.IsDisabled ? (object)new { disabled = "disabled" } : (object)new { })

@ Html.EditorFor (m => m.Description, Model.IsDisabled? (object) new {disabled = "disabled"} : (object) new {}) => 이것이 최선의 방법 인 것 같습니다. 감사합니다
Carmine Checker

23

나는 Darin 방법을 좋아합니다. 하지만이 문제를 빠르게 해결하는 방법은

Html.TextBox("Expiry", null, new { style = "width: 70px;", maxlength = "10", id = "expire-date", disabled = "disabled" }).ToString().Replace("disabled=\"disabled\"", (1 == 2 ? "" : "disabled=\"disabled\""))

1
난 당신이 @ Html.Raw ()와 함께이 문제를 둘러싸고해야한다고 생각
샤디 Namrouti

14

내가 사용한 한 가지 간단한 접근 방식은 조건부 렌더링입니다.

@(Model.ExpireDate == null ? 
  @Html.TextBoxFor(m => m.ExpireDate, new { @disabled = "disabled" }) : 
  @Html.TextBoxFor(m => m.ExpireDate)
)

13

html 도우미를 사용하지 않는 경우 다음과 같은 간단한 삼항 표현식을 사용할 수 있습니다.

<input name="Field"
       value="@Model.Field" tabindex="0"
       @(Model.IsDisabledField ? "disabled=\"disabled\"" : "")>

13

일부 확장 방법을 사용하여 달성했습니다.

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);
    }

그리고....

@Html.TextBoxFor(model => model.Name, new { @class= "someclass"}).IsDisabled(Model.ExpireDate == null)

rawstring.Length-2를 7로 변경하고 마지막에 ""를 추가하면 작동합니다.
Jozef Krchňavý

입력 유형의 모든 종류의 솔루션 TextAreaFor하지 작업 필요합니까
erhan355

10

이것은 늦었지만 어떤 사람들에게는 도움이 될 수 있습니다.

@DarinDimitrov의 답변을 확장하여 disabled="disabled" checked="checked", selected="selected"등 의 부울 html 속성을 취하는 두 번째 개체를 전달할 수 있습니다 .

속성 값이 true 인 경우에만 속성을 렌더링하고 다른 항목과 속성은 전혀 렌더링되지 않습니다.

사용자 정의 재사용 가능한 HtmlHelper :

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;
    }

}

다음과 같이 사용할 수 있습니다.

@Html.MyTextBoxFor(m => Model.Employee.Name
                   , new { @class = "x-large" , placeholder = "Type something…" }
                   , new { disabled = true})

10

RouteValueDictionary (IDictionary를 기반으로하므로 htmlAttributes로 잘 작동 함) 및 확장 메서드를 사용하여 해결됩니다.

public static RouteValueDictionary AddIf(this RouteValueDictionary dict, bool condition, string name, object value)
{
    if (condition) dict.Add(name, value);
    return dict;
}

용법:

@Html.TextBoxFor(m => m.GovId, new RouteValueDictionary(new { @class = "form-control" })
.AddIf(Model.IsEntityFieldsLocked, "disabled", "disabled"))

크레딧은 https://stackoverflow.com/a/3481969/40939이동합니다.


IMHO,이 최고의 답변입니다
JenonD

6

Html Helpers를 사용하고 싶지 않다면 내 솔루션을 살펴보십시오.

disabled="@(your Expression that returns true or false")"

그것은 그

@{
    bool isManager = (Session["User"] as User).IsManager;
}
<textarea rows="4" name="LetterManagerNotes" disabled="@(!isManager)"></textarea>

더 나은 방법은 컨트롤러에서 확인하고 뷰 (Razor 엔진) 내에서 액세스 할 수있는 변수 내에 저장하여 the view free from business logic


7
컨트롤에서 disabled 속성을 사용하면 속성 값에 관계없이 컨트롤이 비활성화됩니다. 값이없는 속성이 있어도 제어가 불가능합니다.
Geeky Guy dec

2
이 솔루션은 정말 잘 작동하며, 반대 투표자들이 표현식이 부울이라는 사실을 간과했을 수 있습니다. 표현식이 부울이면 disabled 속성은 표현식이 true이면 disabled = "disabled"로 렌더링되고 false이면 완전히 생략됩니다. 정확히 당신이 원하는 것입니다.
Carsten

이것은 disabled = "false"또는 disabled = "true"로 렌더링됩니다. 아니오?
Andez 2011

4

또 다른 해결책은 Dictionary<string, object>호출하기 전에을 만들고 TextBoxFor해당 사전을 전달하는 것입니다. 사전 "disabled"에서 텍스트 상자가 비활성화되는 경우에만 키를 추가하십시오 . 가장 깔끔한 솔루션은 아니지만 간단하고 간단합니다.


2

또 다른 방법은 클라이언트 측에서 텍스트 상자를 비활성화하는 것입니다.

귀하의 경우 비활성화해야 할 텍스트 상자가 하나만 있지만 비활성화 할 필요가없는 여러 입력, 선택 및 텍스트 영역 필드가있는 경우를 고려하십시오.

jquery + (클라이언트에서 오는 데이터에 의존 할 수 없기 때문에)를 통해 수행하는 것이 훨씬 쉽습니다. 컨트롤러에 로직을 추가하여 이러한 필드가 저장되지 않도록합니다.

다음은 그 예입니다.

<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);
  }
}

0

확장 메서드 접근 방식을 좋아하므로 가능한 모든 매개 변수를 통과 할 필요가 없습니다.
그러나 정규식을 사용하는 것은 상당히 까다로울 수 있으므로 (그리고 다소 느릴 수 있으므로) XDocument대신 사용 했습니다.

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());
}

다음과 같은 확장 방법을 사용하십시오.
@Html.EditorFor(m => m.MyProperty).SetDisabled(Model.ExpireDate == null)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.