J'ai cette ligne de code:
@Html.EditorFor(model => model.Quantity, new { htmlAttributes = new { @class = "form-control", @readonly = "readonly" } })
J'ai une variable dans mon dictionnaire de données de vue appelée Readonly. Comment faire en sorte que Quantity soit en lecture seule si ViewBag.Readonly
est vrai et non en lecture si elle est fausse?
Simple, mais la combinaison de Razor avec HTML (qui est ancien) rend impossible des choses simples par ailleurs.
Éditions:
Je ne veux pas utiliser une instruction if. C’est un dernier recours car il enfreint DRY que j’ai été gravement brûlé à plusieurs reprises dans le passé pour ne pas avoir suivi.
La ligne que j'ai ci-dessus fonctionne dans la mesure où elle rend la zone de texte en lecture seule. Je dois rendre cette condition conditionnelle en fonction de mon état de vision.
Solution:
J'ai utilisé ce qui suit. Il s'agit toujours d'une violation DRY, mais cela la réduit à une ligne.
@Html.EditorFor(model => model.Quantity, new { htmlAttributes = ViewBag.Readonly ? (object)new { @class = "form-control", @readonly = "htmlsucks" } : (object)new { @class = "form-control" } })
Aujourd’hui, j’ai dû faire face à ce problème, car j’ai dû définir de manière dynamique un attribut "lecture seule" à un élément Html.TextBoxFor
. J'ai fini par écrire la méthode d'assistance suivante qui m'a permis de contourner le problème tout en conservant une approche DRY:
/// <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;
}
Il peut être utilisé de la manière suivante:
var dic = new Dictionary<string,object>();
if (IsReadOnly()) dic.Add("readonly", "readonly");
Html.TextBoxFor(m => m.Name, GetHtmlAttributes(new { @class="someclass" }, dic))
Le code est assez explicite, mais j'ai aussi expliqué la logique sous-jacente dans ce post sur mon blog.
EDIT: MVC 5
Manette
ViewBag.Readonly=true;//false
Vue
@Html.EditorFor(model => model.Quantity, ViewBag.Readonly ? (object)new { htmlAttributes = new { @readonly = "readonly", @class = "form-control" }} : new { htmlAttributes = new { @class = "form-control" } })
C'est très simple. Fais-le comme ça.
@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" } })
}
Si vous avez plusieurs endroits dans votre vue avec une telle logique, je pense qu'en utilisant la bibliothèque FluentDataAnnotations , vous pouvez garder votre code propre et clair.
Si vous connaissez FluentValidator , son utilisation est très similaire.
Dans votre cas, toute la logique sera déplacée d'une vue à la classe d'annotation de modèle. En vous aurez seulement @Html.EditorFor(model => model.Quantity)
Cela permet même d’utiliser les propriétés du modèle dans les conditions. this.When(model => !model.AllowEditPhone,
() => {
this.For(m => m.Phone).SetReadOnly(false);
});
Voici le package NuGet qui nécessite ASP.NET MVC 5. (La prise en charge d’ASP.NET Core est en cours.)
En écrivant une méthode d'assistance, le principe DRY peut être respecté.
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);
}
}
alors à votre avis:
ajoutez une instruction conditionnelle pour déterminer en lecture seule ex.
@{bool IsReadOnly = YourCondition;}
@Html.ConditionalEditFor(!IsReadOnly/*condition*/, model => model.YourProperty,true /*do validation*/)
vous pouvez ensuite ajouter tout autre remplacement que vous souhaitez.
JQUERY pour lire la valeur du contrôle SETUP_TYPE et désactiver les contrôles avec un sélecteur CSS particulier.
$(function () {
if ($("#SETUP_TYPE").val() == "1") { $('.XXX').attr('disabled', true); }
})
$(function () {
if ($("#SETUP_TYPE").val() == "2") { $('.YYY').attr('disabled', true); }
})
Ce contrôle est désactivé si SETUP_TYPE vaut 1 ou 2.
@Html.EditorFor(model => model.CLAIM, new { htmlAttributes = new { @class = "form-control XXX YYY" } })
Ce contrôle est désactivé si SETUP_TYPE est à 1.
@Html.EditorFor(model => model.POLICY, new { htmlAttributes = new { @class = "form-control XXX" } })
Ce contrôle est désactivé si SETUP_TYPE est 2.
@Html.EditorFor(model => model.INSURED, new { htmlAttributes = new { @class = "form-control YYY" } })