web-dev-qa-db-fra.com

Définissez l'attribut disable en fonction d'une condition pour Html.TextBoxFor

Je veux définir l'attribut disable en fonction d'une condition pour Html.TextBoxFor dans asp.net MVC, comme ci-dessous

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

Cette aide a deux sorties disabled = "disabled" ou disabled = "". les deux thèmes font la zone de texte désactivée.

Je veux désactiver la zone de texte si Model.ExpireDate == null sinon je veux l'activer

74
Ghooti Farangi

Le moyen valable est:

disabled="disabled"

Les navigateurs peuvent également accepterdisabled="" mais je vous recommanderais la première approche.

Ceci étant dit, je vous recommanderais d'écrire un assistant HTML personnalisé afin d'encapsuler cette fonctionnalité désactivation dans un morceau de code réutilisable:

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

que vous pourriez utiliser comme ceci:

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

et vous pourriez apporter encore plus intelligence dans cette aide:

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

de sorte que vous n'avez plus besoin de spécifier la condition désactivée:

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

En réalité, le comportement interne traduit l'objet anonyme en dictionnaire. Donc ce que je fais dans ces scénarios est d'aller chercher un dictionnaire:

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

Ou, comme Stephen a commenté ici :

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

J'aime la méthode Darin. Mais moyen rapide de résoudre ce problème,

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

Je l'ai réalisé en utilisant des méthodes d'extension

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

et alors....

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

Si vous n'utilisez pas d'utilitaires HTML, vous pouvez utiliser une expression ternaire simple comme ceci:

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

Une approche simple que j'ai utilisée est le rendu conditionnel:

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

C'est tard, mais peut être utile à certaines personnes.

J'ai étendu la réponse de @ DarinDimitrov pour permettre le passage d'un deuxième objet qui prend un nombre quelconque d'attributs html booléens comme disabled="disabled" checked="checked", selected="selected" etc.

Il ne restituera l'attribut que si la valeur de la propriété est true, tout le reste et l'attribut ne sera pas rendu du tout.

Le custom réutilisable 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;
    }

}

Que vous pouvez utiliser comme ceci:

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

Ceci est résolu en utilisant RouteValueDictionary (fonctionne très bien comme htmlAttributes car il est basé sur IDictionary) et une méthode d'extension:

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

Usage:

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

Le crédit va à https://stackoverflow.com/a/3481969/40939

7
Niels Bosma

si vous ne voulez pas utiliser les Helpers HTML, prenez le, regardez ma solution

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

que ça

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

et je pense que la meilleure façon de le faire est de faire cette vérification dans le contrôleur et de l'enregistrer dans une variable accessible à l'intérieur de la vue (moteur Razor) afin de rendre the view free from business logic

5
Basheer AL-MOMANI

Une autre solution serait de créer un Dictionary<string, object> _ avant d’appeler TextBoxFor et de transmettre ce dictionnaire. Dans le dictionnaire, ajoutez "disabled" _ uniquement si la zone de texte doit être désactivée. Pas la solution la plus simple mais simple et directe.

4
Kjell Rilbe

Une autre approche consiste à désactiver la zone de texte côté client.

Dans votre cas, vous ne devez désactiver qu'un seul champ de texte, mais considérez le cas où vous avez plusieurs champs de saisie, de sélection et de zone de texte que vous devez désactiver.

Il est beaucoup plus facile de le faire via jquery + (car nous ne pouvons pas compter sur les données provenant du client). Ajoutez une logique au contrôleur pour empêcher la sauvegarde de ces champs.

Voici un exemple:

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