ตั้งค่าแอตทริบิวต์ปิดการใช้งานตามเงื่อนไขสำหรับ Html.TextBoxFor

ฉันต้องการตั้งค่าแอตทริบิวต์ปิดการใช้งานตามเงื่อนไขสำหรับ Html.TextBoxFor ใน asp.net MVC เช่นด้านล่าง

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

ตัวช่วยนี้มีเอาต์พุตสองตัวที่พิการ = "ปิดการใช้งาน" หรือปิดการใช้งาน = "" ทั้งสองธีมทำให้กล่องข้อความปิดใช้งาน

ฉันต้องการปิดการใช้งานกล่องข้อความถ้า Model.ExpireDate == null มิฉะนั้นฉันต้องการเปิดใช้งาน


person Ghooti Farangi    schedule 12.07.2011    source แหล่งที่มา
comment
ดูคำตอบของฉันที่นี่: stackoverflow.com/a/43131930/6680521   -  person Extragorey    schedule 31.03.2017


คำตอบ (12)


วิธีที่ถูกต้องคือ:

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" 
    }
)
person Darin Dimitrov    schedule 12.07.2011
comment
ฉันต้องการปิดการใช้งานกล่องข้อความถ้า Model.ExpireDate == null มิฉะนั้นฉันต้องการเปิดใช้งาน - person Ghooti Farangi; 12.07.2011
comment
วิธีแก้ปัญหานี้ดีมาก - เท่าที่เป็นไป... แต่คงจะดีถ้าหาวิธีแก้ปัญหาใหม่ซึ่งไม่จำเป็นต้องใส่ wrapper รอบๆ HtmlHelper ทุกตัวที่เราใช้ซึ่งอาจมีแอตทริบิวต์ที่ถูกปิดใช้งาน (TextBoxFor, TextAreaFor, CheckBoxFor ฯลฯ .) เป็นการดีที่จะเป็นสิ่งที่ทำงานสอดคล้องกับสิ่งที่มีอยู่ ฉันได้สร้างโซลูชันที่โดยพื้นฐานแล้วเพียงแค่ล้อมวัตถุที่ไม่ระบุชื่อและส่งคืน RouteValueDictionary - แต่ก็ไม่ได้รู้สึกว่าสะอาดเป็นพิเศษ - person Mir; 17.12.2012
comment
Disabled, Disable='' และ Disable='disabled' ล้วนถูกต้องเท่าเทียมกันใน html และทำให้เข้าใจผิด (และเป็นเท็จ) หากกล่าวว่าอันที่สั้นกว่านั้นอาจยอมรับโดยเบราว์เซอร์ที่แตกต่างกันเท่านั้น อ้างอิง dev.w3.org/html5/markup/syntax.html# ไวยากรณ์-attr-ว่างเปล่า - person Shautieh; 24.09.2013

ที่จริงแล้วพฤติกรรมภายในกำลังแปลวัตถุที่ไม่ระบุชื่อเป็นพจนานุกรม ดังนั้นสิ่งที่ฉันทำในสถานการณ์เหล่านี้คือไปหาพจนานุกรม:

@{
  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 { })
person Shimmy Weitzhandler    schedule 25.03.2015
comment
@Html.EditorFor(m =› m.Description, Model.IsDisabled ? (object)new { Disable = Disabled } : (object)new { }) =› นี่ดูเหมือนเป็นวิธีที่ดีที่สุด ขอบคุณ - person Carmine Checker; 24.02.2020

ฉันชอบวิธีของดาริน แต่วิธีที่รวดเร็วในการแก้ปัญหานี้

Html.TextBox("Expiry", null, new { style = "width: 70px;", maxlength = "10", id = "expire-date", disabled = "disabled" }).ToString().Replace("disabled=\"disabled\"", (1 == 2 ? "" : "disabled=\"disabled\""))
person user571646    schedule 12.07.2011
comment
ฉันคิดว่าคุณควรล้อมรอบสิ่งนี้ด้วย @Html.Raw() - person Shadi Namrouti; 14.01.2018

วิธีง่ายๆ วิธีหนึ่งที่ฉันใช้คือการเรนเดอร์แบบมีเงื่อนไข:

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

หากคุณไม่ได้ใช้ตัวช่วย html คุณอาจใช้นิพจน์แบบไตรภาคอย่างง่ายดังนี้:

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

ฉันทำสำเร็จโดยใช้วิธีการขยายบางอย่าง

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)
person MurtuzaB    schedule 27.04.2015
comment
ใช้งานได้หากคุณเปลี่ยน rawstring.Length - 2 สำหรับ 7 และเพิ่มหลังจาก Last - person Jozef Krchňavý; 09.05.2017
comment
ใช้ไม่ได้กับ TextAreaFor ต้องการโซลูชันสำหรับอินพุตทุกประเภท - person erhan355; 04.01.2019

ได้รับการแก้ไขโดยใช้ RouteValueDictionary (ทำงานได้ดีเป็น htmlAttributes เนื่องจากเป็นไปตาม IDictionary) และวิธีการขยาย:

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

person Niels Bosma    schedule 29.10.2015
comment
IMHO นี่คือคำตอบที่ดีที่สุด - person JenonD; 08.04.2020

เรื่องนี้ล่าช้าแต่อาจเป็นประโยชน์กับบางคน

ฉันได้ขยายคำตอบของ @DarinDimitrov เพื่ออนุญาตให้ส่งวัตถุที่สองที่รับแอตทริบิวต์ html แบบบูลจำนวนเท่าใดก็ได้เช่น disabled="disabled" checked="checked", selected="selected" เป็นต้น

มันจะเรนเดอร์แอ็ตทริบิวต์เฉพาะเมื่อค่าคุณสมบัติเป็นจริง สิ่งอื่นใดและแอ็ตทริบิวต์จะไม่ถูกเรนเดอร์เลย

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})
person sacritruth    schedule 28.02.2013

หากคุณไม่ต้องการใช้ 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>

และฉันคิดว่าวิธีที่ดีกว่าในการทำคือทำการตรวจสอบในคอนโทรลเลอร์และบันทึกลงในตัวแปรที่สามารถเข้าถึงได้ภายในมุมมอง (เครื่องมือมีดโกน) เพื่อสร้าง the view free from business logic

person Basheer AL-MOMANI    schedule 29.08.2016
comment
หากคุณใช้แอตทริบิวต์ที่ปิดใช้งานในตัวควบคุม ตัวควบคุมจะถูกปิดใช้งานไม่ว่าแอตทริบิวต์จะมีค่าใดก็ตาม แม้แต่การมีอยู่ของแอตทริบิวต์ที่ไม่มีค่าก็จะปิดการใช้งานการควบคุม - person Geeky Guy; 20.12.2016
comment
โซลูชันนี้ใช้งานได้ดีมาก และฉันสงสัยว่าผู้ลงคะแนนเสียงอาจมองข้ามว่านิพจน์นั้นเป็นบูลีน เมื่อนิพจน์เป็นบูลีน คุณลักษณะที่ปิดใช้งานจะแสดงผลเป็น Disable=disabled หากนิพจน์เป็นจริง หรือละไว้โดยสิ้นเชิงหากเป็นเท็จ ซึ่งเป็นสิ่งที่คุณต้องการ - person Carsten; 18.02.2018
comment
สิ่งนี้จะแสดงผล Disable=false หรือ Disable=true ใช่ไหม - person Andez; 21.11.2018

อีกวิธีหนึ่งคือสร้าง Dictionary<string, object> ก่อนที่จะโทร TextBoxFor และส่งพจนานุกรมนั้น ในพจนานุกรม ให้เพิ่มคีย์ "disabled" เฉพาะในกรณีที่ต้องปิดใช้งานกล่องข้อความเท่านั้น ไม่ใช่วิธีแก้ปัญหาที่ประณีตที่สุด แต่เรียบง่ายและตรงไปตรงมา

person Kjell Rilbe    schedule 08.08.2013

อีกวิธีหนึ่งคือการปิดการใช้งานกล่องข้อความในฝั่งไคลเอ็นต์

ในกรณีของคุณ คุณมีเพียงกล่องข้อความเดียวที่คุณต้องปิดการใช้งาน แต่ให้พิจารณากรณีที่คุณมีฟิลด์อินพุต เลือก และพื้นที่ข้อความหลายช่องที่คุณต้องปิดใช้งาน

มันง่ายกว่ามากที่จะทำผ่าน 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);
  }
}
person Dror    schedule 09.09.2012

ฉันชอบวิธีการขยาย ดังนั้นคุณไม่จำเป็นต้องผ่านพารามิเตอร์ที่เป็นไปได้ทั้งหมด
อย่างไรก็ตาม การใช้นิพจน์ทั่วไปอาจค่อนข้างยุ่งยาก (และค่อนข้างช้ากว่า) ดังนั้นฉันจึงใช้ 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)

person Kapé    schedule 05.06.2020