Wie mache ich EditorFor bedingt schreibgeschützt?

Lesezeit: 8 Minuten

Benutzer-Avatar
Jordanien

Ich habe diese Codezeile:

@Html.EditorFor(model => model.Quantity, new { htmlAttributes = new { @class = "form-control", @readonly = "readonly" } })

Ich habe eine Variable in meinem Ansichtsdatenwörterbuch namens Readonly. Wie mache ich Menge schreibgeschützt, wenn ViewBag.Readonly wahr ist und nicht gelesen wird, nur wenn es falsch ist?

Einfache Sache, aber die Kombination von Razor mit HTML (das uralt ist) macht ansonsten einfache Dinge unmöglich.

Bearbeitungen:

Ich möchte keine if-Anweisung verwenden. Das ist ein letzter Ausweg, weil es gegen DRY verstößt, was ich in der Vergangenheit viele Male schwer verbrannt habe, weil ich es nicht befolgt habe.

Die Zeile, die ich oben habe, funktioniert insofern, als sie das Textfeld schreibgeschützt macht. Ich muss dies basierend auf meinem Ansichtszustand bedingt machen.

Lösung:

Ich habe folgendes verwendet. Es ist immer noch eine DRY-Verletzung, aber es reduziert es auf eine Zeile.

@Html.EditorFor(model => model.Quantity, new { htmlAttributes = ViewBag.Readonly ? (object)new { @class = "form-control", @readonly = "htmlsucks" } : (object)new { @class = "form-control" } })

BEARBEITEN: MVC5

Regler

ViewBag.Readonly=true;//false

Aussicht

@Html.EditorFor(model => model.Quantity, ViewBag.Readonly ? (object)new { htmlAttributes = new { @readonly = "readonly", @class = "form-control" }} : new { htmlAttributes = new { @class = "form-control" } })

  • Nett. Ich sehe, wie Sie die DRY-Verletzung minimiert haben. Ich respektiere das. Ich habe die Dinge ein wenig geändert, aber ich denke, ich werde das verwenden. Ich hoffe immer noch auf bessere Optionen, aber das funktioniert vorerst.

    – Jordanien

    20. März 2015 um 18:29 Uhr

  • Dies ist die beste Antwort

    Benutzer4083514

    22. März 2015 um 16:12 Uhr

  • Das Problem dabei ist, wenn Sie einen großen Satz von haben htmlAttributesmüssen Sie alle anderen wiederholen nur um die readonly zu wechseln??? Und es ist noch schlimmer, wenn Sie andere Attribute (ähnlich wie readonly) unabhängig voneinander zusammenschalten können, z disabled, required… Also angenommen, die Anzahl solcher Attribute ist ndu brauchst 2^n Ausdrücke mit duplizierte Einstellungen für andere Attribute. Das ist ein schreckliches Design. Das beste Design ist in diesem Fall, wenn die Eigenschaft auf gesetzt ist null, ignorieren Sie einfach das Rendern. ASP.NET MVC muss noch weiter verbessert werden.

    – König König

    8. Juni 2017 um 1:50 Uhr


Benutzer-Avatar
Dunkelsiegel

Heute musste ich mich mit diesem Problem befassen, da ich ein “schreibgeschütztes” Attribut dynamisch auf a setzen musste Html.TextBoxFor Element. Am Ende schrieb ich die folgende Hilfsmethode, die es mir ermöglichte, das Problem zu umgehen, während ich einen DRY-Ansatz beibehielt:

/// <summary>
/// Gets an object containing a htmlAttributes collection for any Razor HTML helper component,
/// supporting a static set (anonymous object) and/or a dynamic set (Dictionary)
/// </summary>
/// <param name="fixedHtmlAttributes">A fixed set of htmlAttributes (anonymous object)</param>
/// <param name="dynamicHtmlAttributes">A dynamic set of htmlAttributes (Dictionary)</param>
/// <returns>A collection of htmlAttributes including a merge of the given set(s)</returns>
public static IDictionary<string, object> GetHtmlAttributes(
    object fixedHtmlAttributes = null,
    IDictionary<string, object> dynamicHtmlAttributes = null
    )
{
    var rvd = (fixedHtmlAttributes == null)
        ? new RouteValueDictionary()
        : HtmlHelper.AnonymousObjectToHtmlAttributes(fixedHtmlAttributes);
    if (dynamicHtmlAttributes != null)
    {
        foreach (KeyValuePair<string, object> kvp in dynamicHtmlAttributes)
            rvd[kvp.Key] = kvp.Value;
    }
    return rvd;
}

Es kann auf folgende Weise verwendet werden:

var dic = new Dictionary<string,object>();
if (IsReadOnly()) dic.Add("readonly", "readonly");
Html.TextBoxFor(m => m.Name, GetHtmlAttributes(new { @class="someclass" }, dic))

Der Code ist ziemlich selbsterklärend, aber ich habe auch die zugrunde liegende Logik in erklärt dieser Beitrag auf meinem Blog.

  • Immer noch ziemlich hässlicher Rasiercode, aber ich kann damit arbeiten. Danke, Anstelle eines Wörterbuchs würde ich wahrscheinlich eine Übersetzungsschicht erstellen, die sich ändern würde readonly=true zu readonly="readonly" und entfernen readonly=false sodass read-only auf einen booleschen Wert gesetzt werden kann. Dumme HTML-Spezifikation mit deinen wertlosen Attributen! Deshalb normalisieren wir Schnittstellen. Ich wünschte, ich könnte die Zeit zurückdrehen und manchmal jemanden schlagen.

    – Jordanien

    14. November 2018 um 16:16 Uhr


  • @Jordan , der Hauptvorteil dieser Problemumgehung besteht darin, dass sie auch verwendet werden kann, um andere Eigenschaftseinstellungen und / oder bewertete Attribute (einschließlich, aber nicht beschränkt auf, schreibgeschützt) dynamisch festzulegen.

    – Dunkelsiegel

    14. November 2018 um 17:38 Uhr


  • Richtig, aber das Problem mit dem OP war mit wertlosen Attributen, die eher klein sind. Die einzigen, die mir einfallen, sind readonly und disabled. Dies sind die einzigen wirklichen Probleme, wenn Sie darüber nachdenken. Sie sind die einzigen Attribute, die Sie nicht einfach leer lassen können.

    – Jordanien

    14. November 2018 um 20:04 Uhr


Benutzer-Avatar
ataravati

Es ist sehr einfach. Mach es so.

@if((bool)ViewBag.Readonly)
{
    @Html.EditorFor(model => model.Quantity, new { htmlAttributes = new { @class = "form-control", @readonly = "readonly" } })
}
else
{
    @Html.EditorFor(model => model.Quantity, new { htmlAttributes = new { @class = "form-control" } })
}

  • Sie können HTML-Attribute an übergeben Html.EditorFor in MVC5 (Ich hätte klarer sein sollen, welche Version von MVC ich verwende.) Der Code, den ich oben habe, macht das Textfeld schreibgeschützt. Ich weiß nicht, wie ich das ohne eine if-Anweisung bedingt machen soll (wieder hätte klarer sein sollen, sorry).

    – Jordanien

    19. März 2015 um 19:32 Uhr

  • Warum willst du nicht ein verwenden if Aussage?

    – ataravati

    19. März 2015 um 19:34 Uhr

  • Kein Problem. Ich habe mich in der Vergangenheit verbrannt, weil ich das DRY-Prinzip nicht befolgt habe. Eine einzige zweiteilige if-Anweisung mit sehr einfachem Inhalt scheint keine große Sache zu sein, aber sie kann wachsen, wenn Sie den Code im Laufe der Zeit ändern. Ich werde dies tun, wenn sich keine andere Lösung bietet, aber das scheint nur eine Schwäche im Fleck zu sein, dies nicht tun zu können. HTML sollte readonly=’true|false’ verwenden, nicht diesen Nur-Namen-Attribut-Unsinn, den sie immer noch haben.

    – Jordanien

    19. März 2015 um 19:37 Uhr

  • Und es ist WIRKLICH hässlicher Code, if-Anweisungen überall dort zu haben, wo Sie etwas so Einfaches tun möchten, wie ein Feld bedingt schreibgeschützt zu machen. Ich mag es, wenn mein Code für Menschen lesbar ist. Ich kann sehen, ob ich die Integer-Vorlage hacken und dies selbst tun kann, um diese Situation zu vermeiden. Ich muss herausfinden, wie das geht. …

    – Jordanien

    19. März 2015 um 19:39 Uhr

  • Ich stimme zu, dass es hässlich ist. Aber es gibt keine andere Möglichkeit. Es sei denn, Sie möchten AngularJS verwenden, was meiner Meinung nach völlig unnötig ist, wenn Sie es nur für diesen Zweck verwenden möchten.

    – ataravati

    19. März 2015 um 19:42 Uhr


Falls Sie viele Orte mit einer solchen Logik sehen, denke ich, die Bibliothek zu verwenden FluentDataAnnotations kann Ihren Code sauber und klar halten.

Wenn Sie sich auskennen FluentValidatores ist sehr ähnlich mit.

In Ihrem Fall wird die gesamte Logik von einer Ansicht in eine Modellanmerkungsklasse verschoben. In werden Sie nur haben @Html.EditorFor(model => model.Quantity)

Es erlaubt sogar, Modelleigenschaften in Bedingungen zu verwenden, z
this.When(model => !model.AllowEditPhone,
() => {
this.For(m => m.Phone).SetReadOnly(false);
});

Hier die NuGet-Paket dafür ist ASP.NET MVC 5 erforderlich. (Unterstützung für ASP.NET Core ist in Arbeit.)

Durch das Schreiben einer Hilfsmethode kann das DRY-Prinzip respektiert werden.

    using System.Web.Mvc.Html;

    public static MvcHtmlString Concat(this MvcHtmlString first, params MvcHtmlString[] strings)
    {
        return MvcHtmlString.Create(first.ToString() + string.Concat(strings.Select(s => ( s == null ? "" : s.ToString()))));
    }

    public static MvcHtmlString ConditionalEditFor<TModel,TValue>(this HtmlHelper<TModel> helper, bool EditCondition, Expression<Func<TModel, TValue>> Expression)
    {
        helper.ConditionalEditFor(EditCondition,Expression,false);
    }

    public static MvcHtmlString ConditionalEditFor<TModel, TValue>(this HtmlHelper<TModel> helper, bool EditCondition, Expression<Func<TModel, TValue>> Expression, bool IncludeValidationOnEdit)
    {
        if (EditCondition)
        {
            if (!IncludeValidationOnEdit)
                return EditorExtensions.EditorFor<TModel, TValue>(helper, Expression);
            else
                return EditorExtensions.EditorFor<TModel, TValue>(helper, Expression).Concat(ValidationExtensions.ValidationMessageFor<TModel, TValue>(helper, Expression));
        }
        else
        {
            return DisplayExtensions.DisplayFor<TModel, TValue>(helper, Expression);
        }
    }

dann aus deiner sicht:

fügen Sie eine bedingte Anweisung hinzu, um Readonly zu bestimmen, z

@{bool IsReadOnly = YourCondition;}

@Html.ConditionalEditFor(!IsReadOnly/*condition*/, model => model.YourProperty,true /*do validation*/)

Sie können dann beliebige andere Überschreibungen hinzufügen, die Sie möchten.

Benutzer-Avatar
Matt

JQUERY zum Lesen des SETUP_TYPE-Steuerwerts und zum Deaktivieren von Steuerelementen mit einem bestimmten CSS-Selektor.

$(function () {
    if ($("#SETUP_TYPE").val() == "1") { $('.XXX').attr('disabled', true); }
})

$(function () {
    if ($("#SETUP_TYPE").val() == "2") { $('.YYY').attr('disabled', true); }
})

Dieses Steuerelement ist deaktiviert, wenn SETUP_TYPE 1 oder 2 ist.

@Html.EditorFor(model => model.CLAIM, new { htmlAttributes = new { @class = "form-control XXX YYY" } })

Dieses Steuerelement ist deaktiviert, wenn SETUP_TYPE 1 ist.

@Html.EditorFor(model => model.POLICY, new { htmlAttributes = new { @class = "form-control XXX" } })

Dieses Steuerelement ist deaktiviert, wenn SETUP_TYPE 2 ist.

@Html.EditorFor(model => model.INSURED, new { htmlAttributes = new { @class = "form-control YYY" } })

Sie können eine IHtmlHelper-Erweiterung mit zusätzlichen Parametern schreiben:

public static IHtmlContent ReadonlyishTextBoxFor<TModel, TProperty>(this IHtmlHelper<TModel> helper,
    Expression<Func<TModel, TProperty>> expression, object htmlAttributes = null, bool shouldBeReadonly = false)
{
    var attributes = new Dictionary<string, object>();
    if (htmlAttributes != null)
    {
        foreach (var propertyInfo in htmlAttributes.GetType().GetProperties())
        {
            attributes.Add(propertyInfo.Name, propertyInfo.GetValue(htmlAttributes));
        }
    }

    if (shouldBeReadonly)
    {
        attributes.Add("readonly", "readonly");
    }

    return helper.TextBoxFor(expression, format: null, attributes);
}

Rasierer:

@Html.ReadonlyishTextBoxFor(p => p.Email, new { @class = "form-control" }, true )
@Html.ReadonlyishTextBoxFor(p => p.Email, new { @class = "form-control" } )

1051850cookie-checkWie mache ich EditorFor bedingt schreibgeschützt?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy