ProgramingTip

MVC 3 : HtmlHelpers를 사용하여 추가 된 특성을 조건부로 추가

bestdevel 2020. 11. 5. 08:15
반응형

MVC 3 : HtmlHelpers를 사용하여 추가 된 특성을 조건부로 추가


ASP.Net MVC 3 웹 응용 프로그램은 다음과 같이 HtmlHelper 클래스를 사용하여 페이지에 추가하고 있습니다.

@Html.CheckBox("CheckBox1", true, new { @class = "Class1" })

내가 원하는대로 추가 된 속성을 조건부로 추가하는 것입니다. 기본적으로 다음이 카드입니다 ...

@Html.CheckBox("CheckBox1", true, new { @class = "Class1", @disabled = Model.ReadOnly })

불행하게도 인해 장애인 속성의 특성이 언어 작업 때문에 어떤 장애인 속성 (심지어 "거짓")에 할당 된 값을 true로 변환합니다.

나는 이미이 문제를 해결하는 수있는 몇 가지 해결 방법을 생각합니다. 그러나 오히려 위의 원하는 방법과 같은 간단한 방법이 있습니까? 또는 다음 중 하나에 의지해야합니까? ..

내가 할 수있는 건 ...

  1. if / else 문을 만들고 다른 Html.CheckBox줄에 씁니다 (가독성에 좋지 않음-마크 업 경고를 유의서 가능-확실하지 않음)

  2. HtmlHelper 클래스를 건너 뛰고 더 나은 조건부 속성을 허용하는 태그를 직접 작성합니다 (코드는 짧아 지지만 불일치를 추가 함).

  3. "disabled"매개 변수를 사용하는 사용자 지정 도우미를 만듭니다 (가장 솔루션이지만 원치 않는 추가 메서드가 필요합니다.)


보기 / 도우미 어딘가에 정의

@functions {
 object getHtmlAttributes (bool ReadOnly, string CssClass) 
 {
     if (ReadOnly) {
         return new { @class = CssClass, @readonly = "readonly" };
     }
     return new { @class = CssClass };
 }
}

그런 다음 사용하십시오.

@Html.TextBox("name", "value", @getHtmlAttributes(Model.ReadOnly, "test"))

이 질문에 대한 내 대답은 다음과 대답합니다. https://stackoverflow.com/a/13922813/495000


다음 도우미를 만들었습니다. 부울과 익명 개체를 사용합니다. disabled가 true이면 "disabled"값이있는 익명 객체 (실제로는 Dictionary)에 비활성화 된 속성을 추가합니다. 확장 할 속성을 전혀 추가하지 않습니다.

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

   if (disabled)
      dictionary.Add("disabled", "disabled");

   return dictionary;
}

실제 동작의 예 :

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

이 접근 방식의 큰 장점 중 하나는 거의 모든 MVC HtmlHelper에서 익명 개체 대신 RouteValueDictionary를 허용하는 오버로드가 있기 때문에 작동한다는 것입니다.

주의 사항 :
HtmlHelper.AnonymousObjectToHtmlAttributes()멋진 코드 닌자 작업을 사용하여 작업을 수행합니다. 나는 그것이 얼마나 성능이 좋은지 완전히 확신하지 못하지만 ... 내가 그것을 사용하는 데 충분했습니다. 귀하의 마일리지가 다를 수 있습니다.

나는 그 이름이 특히 마음에 들지 않습니다. 그러나 더 좋은 것을 생각할 수 없습니다. 이름 변경은 제출.

또한 사용 구문이 마음에 들지 언어입니다. 그러나 다시 한 번 더 나은 방법을 수 없습니다. 변경하기 어렵지 않습니다. 하나의 아이디어에 대한 확장 방법은 하나의 아이디어입니다 ... 끝낼 수는 new { @class = "someClass" }.ConditionalDisable(true)추가 사항이없는 경우에만 원하고 추가 할 수있는 것과 같은 new {}.ConditionalDisable(true);결과가 발생하고 확장 기능도 있습니다. 모두 object에게 방법 ... 아마 모든 것입니다.


헬퍼 함수없이 더 간결한 구문을 사용 @ HTML.Checkbox 헬퍼의 html 속성에 사전을 정의 할 때 삼 항문을 사용할 수 있습니다.

@Html.CheckBox("CheckBox1", true, Model.ReadOnly 
       ? new { @class = "Class1", @disabled = Model.ReadOnly } 
       : null)

이 경우 Model.ReadOnly는 false이고 null은 html 속성의 사전으로 전달됩니다.


강화 된 속성 클라이언트 추가를 수행하는 것이 저에게 측입니다. 서버 측에서 편집 할 수있는 필드를 확인해야하지만 비활성화 된 속성이 장식으로 선언 될 경우에도 마찬가지입니다.

이 예에서는 jQuery를 사용하여 양식의 모든 하위 항목을 계속했습니다.

    if (Model.CanEdit)
    {
        <script type="text/javascript">

            $(document).ready(function() {

                $('#editForm *').attr('disabled', true);
            });

        </script>
    }

@Html.TextBoxFor(m => m.FieldName, Html.FixBoolAttributes(new {
    @class = "myClass",
    @readonly = myFlag  
}))


public static class BooleanAttributeFix
{
    /// <summary>
    /// Normalises HTML boolean attributes so that readonly=true becomes readonly="readonly" and
    /// readonly=false removes the attribute completely.
    /// </summary>
    /// <param name="htmlHelper"></param>
    /// <param name="htmlAttributes"></param>
    /// <returns></returns>
    public static RouteValueDictionary FixBoolAttributes(this HtmlHelper htmlHelper, object htmlAttributes)
    {
        var attrs = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);

        foreach(var attrName in new[] { "disabled", "readonly" })
        {
            object value;
            if(attrs.TryGetValue(attrName, out value))
            {
                if(isTruthy(value))
                {
                    // Change from readonly="true" to readonly="readonly"
                    attrs[attrName] = attrName; 
                }
                else
                {
                    // Remove attribute entirely
                    attrs.Remove(attrName); 
                }
            }
        }
        return attrs;
    }

    /// <summary>
    /// Apply similar loose rules like javascript does for whether a value is true or not.
    /// e.g. 1 = true, non-empty string = true and so on.
    /// </summary>
    /// <param name="val"></param>
    /// <returns></returns>
    private static bool isTruthy(object val)
    {   
        if(val == null)
            return false;

        if(val is string)
        {
            return !String.IsNullOrEmpty((string)val);
        }

        Type t = val.GetType();

        if(t.IsValueType && Nullable.GetUnderlyingType(t) == null)
        {
            // If a non-nullable value type such as int we want to check for the
            // default value e.g. 0.
            object defaultValue = Activator.CreateInstance(t);

            // Use .Equals to compare the values rather than == as we want to compare
            // the values rather than the boxing objects.
            // See http://stackoverflow.com/questions/6205029/comparing-boxed-value-types
            return !val.Equals(defaultValue);
        }

        return true;
    }
}


간단한 솔루션 에 대해 어떻게 생각 하십니까? 가능한 두 HtmlAttributes유형 모두에서 쉽게 작동 합니다.

  • Dictionary<string, object>
  • Anonymous Object:

먼저extension class프로젝트에 다음을 추가하십시오 .

public static class HtmlAttributesExtensions
{
    public static IDictionary<string, object> AddHtmlAttrItem(this object obj, string name, object value, bool condition)
    {
        var items= !condition ? new RouteValueDictionary(obj) : new RouteValueDictionary(obj) {{name, value}};
        return UnderlineToDashInDictionaryKeys(items);
    }
    public static IDictionary<string, object> AddHtmlAttrItem(this IDictionary<string, object> dictSource, string name, object value, bool condition)
    {
        if (!condition)
            return dictSource;

        dictSource.Add(name, value);
        return UnderlineToDashInDictionaryKeys(dictSource);
    }
    private static IDictionary<string, object> UnderlineToDashInDictionaryKeys(IDictionary<string,object> items)
    {
        var newItems = new RouteValueDictionary();
        foreach (var item in items)
        {
            newItems.Add(item.Key.Replace("_", "-"), item.Value);
        }
        return newItems;
    }
}

이제보기 :

예 1 ( HtmlAttributestype as Anonymous Object)

@{
  var hasDisabled=true; 
}

@Html.CheckBox("CheckBox1"
              , true
              , new { @class = "Class1"}
               .AddHtmlAttrItem("disabled", "disabled", hasDisabled))
.

예제 2 ( HtmlAttributestype as Dictionary<string, object>)

@Html.CheckBox("CheckBox1"
              , true
              , new Dictionary<string, object> { { "class", "Class1" }
               .AddHtmlAttrItem("disabled", "disabled", hasDisabled))
.

이제 hasDisabled값을 true또는 false!


예 3 (복제 조건부 속성)

@{
  var hasDisabled=true;
  var hasMax=false ;
  var hasMin=true ;
}

@Html.CheckBox("CheckBox1"
              , true
              , new { @class = "Class1"}
               .AddHtmlAttrItem("disabled", "disabled", hasDisabled)
               .AddHtmlAttrItem("data-max", "100", hasMax)
               .AddHtmlAttrItem("data-min", "50", hasMin))
.

참고 URL : https://stackoverflow.com/questions/7978137/mvc-3-conditionally-adding-the-disabled-attribute-with-the-htmlhelpers

반응형