web-dev-qa-db-fra.com

ASP.NET MVC 3 Razor - Ajout d'une classe à EditorFor

J'essaie d'ajouter une classe à une entrée.

Cela ne fonctionne pas:

@Html.EditorFor(x => x.Created, new { @class = "date" })
181
user137348

Ajouter une classe à Html.EditorFor n'a pas de sens, car dans son modèle, vous pourriez avoir beaucoup de balises différentes. Vous devez donc assigner la classe dans le modèle d’éditeur:

@Html.EditorFor(x => x.Created)

et dans le modèle personnalisé:

<div>
    @Html.TextBoxForModel(x => x.Created, new { @class = "date" })
</div>
179
Darin Dimitrov

À partir d'ASP.NET MVC 5.1, il est possible d'ajouter une classe à un EditorFor (la question d'origine spécifiait ASP.NET MVC 3 et la réponse acceptée demeurait la meilleure avec celle considérée).

@Html.EditorFor(x=> x.MyProperty,
    new { htmlAttributes = new { @class = "MyCssClass" } })

Voir: Nouveautés de ASP.NET MVC 5.1, Prise en charge de Bootstrap pour les modèles d'éditeur

142
EF0

Vous ne pouvez pas définir la classe pour le EditorFor générique. Si vous connaissez l'éditeur que vous voulez, vous pouvez l'utiliser immédiatement, vous pouvez y définir la classe. Vous n'avez pas besoin de créer de modèles personnalisés.

@Html.TextBoxFor(x => x.Created, new { @class = "date" }) 
101
TuomasK

Vous pouvez utiliser:

@Html.EditorFor(x => x.Created, new { htmlAttributes = new { @class = "date" } })

(Au moins avec ASP.NET MVC 5, mais je ne sais pas comment c'était avec ASP.NET MVC 3.)

36
przno

J'avais le même problème frustrant et je ne voulais pas créer un EditorTemplate qui s'appliquait à toutes les valeurs DateTime (il y avait des moments dans mon interface utilisateur où je voulais afficher l'heure et non un jQuery UI drop calendrier en bas). Dans mes recherches, les problèmes fondamentaux que j'ai rencontrés étaient les suivants:

  • L’aide standard de TextBoxFor m’a permis d’appliquer une classe personnalisée de "date-picker" afin de rendre le calendrier discret de l’interface utilisateur jQuery, mais TextBoxFor ne formaterait pas un DateTime sans l'heure, ce qui entraîne l'échec du rendu du calendrier.
  • Le standard EditorFor affiche le DateTime sous forme de chaîne mise en forme (lorsqu'il est décoré des attributs appropriés tels que [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")], mais il ne permet pas moi d'appliquer la classe personnalisée "date-picker".

Par conséquent, j'ai créé une classe HtmlHelper personnalisée qui présente les avantages suivants:

  • La méthode convertit automatiquement DateTime en ShortDateString nécessaire au calendrier jQuery (jQuery échouera si l'heure est présente).
  • Par défaut, l'assistant appliquera les attributs htmlAttributes requis pour afficher un calendrier jQuery, mais ils peuvent être remplacés si nécessaire.
  • Si la date est null, ASP.NET MVC mettra une date de 1/1/0001 en tant que valeur.

Cette méthode remplace celle-ci par une chaîne vide.

public static MvcHtmlString CalenderTextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes = null)
{
    var mvcHtmlString = System.Web.Mvc.Html.InputExtensions.TextBoxFor(htmlHelper, expression, htmlAttributes ?? new { @class = "text-box single-line date-picker" });
    var xDoc = XDocument.Parse(mvcHtmlString.ToHtmlString());
    var xElement = xDoc.Element("input");
    if (xElement != null)
    {
        var valueAttribute = xElement.Attribute("value");
        if (valueAttribute != null)
        {
            valueAttribute.Value = DateTime.Parse(valueAttribute.Value).ToShortDateString();
            if (valueAttribute.Value == "1/1/0001")
                valueAttribute.Value = string.Empty;
        }
    }
    return new MvcHtmlString(xDoc.ToString());
}

Et pour ceux qui veulent connaître la syntaxe JQuery qui recherche les objets avec la décoration de classe date-picker pour ensuite afficher le calendrier, la voici:

$(document).ready(function () {
    $('.date-picker').datepicker({ inline: true, maxDate: 0, changeMonth: true, changeYear: true });
    $('.date-picker').datepicker('option', 'showAnim', 'slideDown');
});
29
bigmac

Il est possible de fournir une classe ou d'autres informations via AdditionalViewData. J'utilise cette option pour permettre à un utilisateur de créer un formulaire basé sur des champs de base de données (propertyName, editorType et editorClass).

Basé sur votre exemple initial:

@Html.EditorFor(x => x.Created, new { cssClass = "date" })

et dans le modèle personnalisé:

<div>
    @Html.TextBoxFor(x => x.Created, new { @class = ViewData["cssClass"] })
</div>
15
Brett

Aucune substitution EditorFor ne vous permet de transmettre un objet anonyme dont les propriétés seraient en quelque sorte ajoutées aux attributs de certaines balises, en particulier pour les modèles d'éditeur intégrés. Vous devrez écrire votre propre modèle d'éditeur personnalisé et transmettre la valeur souhaitée en tant que viewdata supplémentaire.

8
marcind
@Html.EditorFor(m=>m.Created ...) 

n'autorise aucun argument à être transmis pour la zone de texte

Voici comment vous pouvez appliquer des attributs.

@Html.TextBoxFor(m=>m.Created, new { @class= "date", Name ="myName", id="myId" })
2
Jayant Varshney

Avec jQuery, vous pouvez le faire facilement:

$("input").addClass("class-name")

Voici votre tag d'entrée

@Html.EditorFor(model => model.Name)

Pour DropDownlist, vous pouvez utiliser celui-ci:

$("select").addClass("class-name")

Pour la liste déroulante:

@Html.DropDownlistFor(model=>model.Name)
2
Praveen M P

J'ai utilisé une autre solution utilisant des sélecteurs d'attributs CSS pour obtenir ce dont vous avez besoin.

Indiquez l'attribut HTML que vous connaissez et indiquez le style relatif souhaité.

Comme ci-dessous:

input[type="date"]
{
     width: 150px;
}
1
Max Clapton

Il n'est pas nécessaire de créer un modèle personnalisé pour MVC 4. Utilisez TextBox au lieu de EditFor ici, les attributs HTML spéciaux ne sont pas pris en charge. Ils ne sont pris en charge que par MVC 5. TextBox doit prendre en charge MVC 4, je ne sais pas pour une autre version.

@Html.TextBox("test", "", new { @id = "signupform", @class = "form-control", @role = "form",@placeholder="Name" })
1
Merbin Jo

Alors que la question visait MVC 3.0, nous constatons que le problème persiste également dans MVC 4.0. MVC 5.0 inclut maintenant de manière native une surcharge pour htmlAttributes.

Je suis obligé d'utiliser MVC 4.0 sur mon lieu de travail actuel et j'ai besoin d'ajouter une classe CSS pour l'intégration JQuery. J'ai résolu ce problème en utilisant une seule méthode d'extension ...

Méthode d'extension:

using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;
using System.Xml.Linq;

namespace MyTest.Utilities
{
    public static class MVCHelperExtensionMethods
    {
        public static MvcHtmlString AddHtmlAttributes(this MvcHtmlString input, object htmlAttributes)
        {
            // WE WANT TO INJECT INTO AN EXISTING ELEMENT.  IF THE ATTRIBUTE ALREADY EXISTS, ADD TO IT, OTHERWISE
            // CREATE THE ATTRIBUTE WITH DATA VALUES.

            // USE XML PARSER TO PARSE HTML ELEMENT
            var xdoc = XDocument.Parse(input.ToHtmlString());
            var rootElement = (from e in xdoc.Elements() select e).FirstOrDefault();

            // IF WE CANNOT PARSE THE INPUT USING XDocument THEN RETURN THE ORIGINAL UNMODIFIED.
            if (rootElement == null)
            {
                return input;
            }

            // USE RouteValueDictionary TO PARSE THE NEW HTML ATTRIBUTES
            var routeValueDictionary = new RouteValueDictionary(htmlAttributes);

            foreach (var routeValue in routeValueDictionary)
            {
                var attribute = rootElement.Attribute(routeValue.Key);

                if (attribute == null)
                {
                    attribute = new XAttribute(name: routeValue.Key, value: routeValue.Value);
                    rootElement.Add(attribute);
                }
                else
                {
                    attribute.Value = string.Format("{0} {1}", attribute.Value, routeValue.Value).Trim();
                }
            }

            var elementString = rootElement.ToString();
            var response = new MvcHtmlString(elementString);
            return response;
        }
    }
}

HTML Markup Usage:

@Html.EditorFor(expression: x => x.MyTestProperty).AddHtmlAttributes(new { @class = "form-control" })

(Assurez-vous d'inclure l'espace de nom de la méthode d'extension dans la vue rasoir)

Explication: L'idée est d'injecter dans le code HTML existant. J'ai choisi d'analyser l'élément actuel à l'aide de Linq-to-XML à l'aide de XDocument.Parse(). Je passe les htmlAttributes comme type object. J'utilise MVC RouteValueDictionary pour analyser les htmlAttributes transmis. Je fusionne les attributs là où ils existent déjà, ou j'ajoute un nouvel attribut s'il n'existe pas encore.

Dans le cas où l'entrée n'est pas analysable par XDocument.Parse() j'abandonne tout espoir et renvoie la chaîne d'entrée d'origine.

Maintenant, je peux utiliser les avantages de DisplayFor (types de données de rendu tels que la devise, de manière appropriée), mais aussi avoir la possibilité de spécifier des classes CSS (et tout autre attribut). Cela pourrait être utile pour ajouter des attributs tels que data-* ou ng-* (Angulaire).

1
barrypicker

Vous pouvez créer le même comportement en créant un éditeur personnalisé simple appelé DateTime.cshtml, en l'enregistrant dans Views/Shared/EditorTemplates.

@model DateTime

@{
    var css = ViewData["class"] ?? "";
    @Html.TextBox("", (Model != DateTime.MinValue? Model.ToString("dd/MM/yyyy") : string.Empty), new { @class = "calendar medium " + css});
}

et dans vos vues

@Html.EditorFor(model => model.StartDate, new { @class = "required" })

Notez que dans mon exemple, je codifie en dur deux classes CSS et le format de date. Vous pouvez bien sûr changer cela. Vous pouvez également faire la même chose avec d'autres attributs HTML, tels que readonly, disabled, etc.

1
Alexandre

Un meilleur moyen d’appliquer une classe à @Html.EditorFor() dans MVC3 RAzor est

@Html.EditorFor(x => x.Created)


<style type="text/css">

#Created
{
    background: #EEE linear-gradient(#EEE,#EEE);   
    border: 1px solid #adadad;
    width:90%;
    }
</style>

Il va ajouter du style ci-dessus à votre EditorFor()

Cela fonctionne pour MVC3.

0
Bilal

Je devais simplement définir la taille d'un champ de texte sur une page. Le codage des attributs sur le modèle et la création de modèles d'éditeur personnalisés étaient excessifs. Je viens donc d'encapsuler l'appel @ Html.EditorFor avec une balise span qui appelle une classe qui spécifie la taille de la zone de texte.

Déclaration de classe CSS:

.SpaceAvailableSearch input
{
    width:25px;
}

Voir le code:

<span class="SpaceAvailableSearch">@Html.EditorFor(model => model.SearchForm.SpaceAvailable)</span>
0
Earl

Vous pouvez aussi le faire via jQuery:

$('#x_Created').addClass(date);
0
Scott R. Frost