web-dev-qa-db-fra.com

Comment modifier LabelFor pour afficher un astérisque dans les champs obligatoires?

Je veux créer une méthode d'extension pour HtmlHelper qui me permet de créer une propriété LabelFor et d'afficher un astérisque après si c'est un champ obligatoire Comment puis je faire ça?

public class Foo
{
    [Required]
    public string Name { get; set; }
}

Html.LabelFor(o => o.Name) // Name*
64
BrunoLM

Voici un article blog qui décrit comment procéder.

Pour vous donner un petit exemple modifié à partir du site ci-dessus (remarque - je n'ai pas compilé/testé cela):

namespace HelpRequest.Controllers.Helpers
{
   public static class LabelExtensions
    {
        public static MvcHtmlString Label(this HtmlHelper html, string expression, string id = "", bool generatedId = false)
        {
            return LabelHelper(html, ModelMetadata.FromStringExpression(expression, html.ViewData), expression, id, generatedId);
        }

        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]
        public static MvcHtmlString LabelFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, string id = "", bool generatedId = false)
        {
            return LabelHelper(html, ModelMetadata.FromLambdaExpression(expression, html.ViewData), ExpressionHelper.GetExpressionText(expression), id, generatedId);
        }

        internal static MvcHtmlString LabelHelper(HtmlHelper html, ModelMetadata metadata, string htmlFieldName, string id, bool generatedId)
        {
            string labelText = metadata.DisplayName ?? metadata.PropertyName ?? htmlFieldName.Split('.').Last();
            if (String.IsNullOrEmpty(labelText))
            {
                return MvcHtmlString.Empty;
            }
            var sb = new StringBuilder();
            sb.Append(labelText);
            if (metadata.IsRequired)
                sb.Append("*");

            var tag = new TagBuilder("label");
            if (!string.IsNullOrWhiteSpace(id))
            {
                tag.Attributes.Add("id", id);
            }
            else if (generatedId)
            {
                tag.Attributes.Add("id", html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(htmlFieldName) + "_Label");
            }

            tag.Attributes.Add("for", html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(htmlFieldName));
            tag.SetInnerText(sb.ToString());

            return MvcHtmlString.Create(tag.ToString(TagRenderMode.Normal));
        }
    }
}
37
JasCav

Vous pouvez ajouter un astérisque à un champ obligatoire uniquement via CSS.

Commencez par créer une classe CSS:

.required:after 
{
    content: "*";
    font-weight: bold;
    color: red; 
}

Cela ajoutera un astérisque rouge à tout élément de la classe "requis".

Ensuite, à votre avis, ajoutez simplement la nouvelle classe à votre étiquette:

    @Html.LabelFor(m => m.Name, new { @class="required" })

Mieux encore, un assistant HTML personnalisé peut déterminer si le champ possède un attribut [Obligatoire] et, le cas échéant, ajoute la classe CSS required.

113
Roger Rouse

C'est ce que j'ai fait car mes champs obligatoires doivent être dynamiques (définis dans un fichier de configuration)

Ajoutez à la fin de votre vue:

    <script type="text/javascript">
        $('input[type=text]').each(function () {
            var req = $(this).attr('data-val-required');
            if (undefined != req) {
                var label = $('label[for="' + $(this).attr('id') + '"]');
                var text = label.text();
                if (text.length > 0) {
                    label.append('<span style="color:red"> *</span>');
                }
            }
        });
    </script>
20
Renato Saito

Voici ma solution basée sur la réponse d'Adam Tuliper mais modifiée pour fonctionner avec Bootstrap et permettre également l'utilisation de attributs personnalisés.

using System;
using System.Linq;
using System.Web.Mvc;
using System.Linq.Expressions;
using System.ComponentModel;


public static class RequiredLabel
{
    public static MvcHtmlString RequiredLabelFor<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression, object htmlAttributes)
    {
        var metaData = ModelMetadata.FromLambdaExpression(expression, helper.ViewData);

        string htmlFieldName = ExpressionHelper.GetExpressionText(expression);
        string labelText = metaData.DisplayName ?? metaData.PropertyName ?? htmlFieldName.Split('.').Last();

        if (metaData.IsRequired)
            labelText += "<span class=\"required\">*</span>";

        if (String.IsNullOrEmpty(labelText))
            return MvcHtmlString.Empty;

        var label = new TagBuilder("label");
        label.Attributes.Add("for", helper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(htmlFieldName));

        foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(htmlAttributes))
        {
            label.MergeAttribute(prop.Name.Replace('_', '-'), prop.GetValue(htmlAttributes).ToString(), true);
        }

        label.InnerHtml = labelText;
        return MvcHtmlString.Create(label.ToString());
    }

}

Ensuite, je l’appelle comme suit:

@Html.RequiredLabelFor(model => model.Category, new { @class = "control-label col-md-3" })

P.S. Assurez-vous de ne pas oublier d'inclure votre espace de noms dans votre vue.

19
Maxime

voir cet article ici - devrait contenir l'essentiel de ce dont vous avez besoin http://blogs.planetcloud.co.uk/mygreatdiscovery/post/Creating-tooltips-using-data-annotations-in-ASPNET-MVC.aspx

public static MvcHtmlString RequiredLabelFor<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression)
{
    var metaData = ModelMetadata.FromLambdaExpression(expression, helper.ViewData);

    string htmlFieldName = ExpressionHelper.GetExpressionText(expression);
    string labelText = metaData.DisplayName ?? metaData.PropertyName ?? htmlFieldName.Split('.').Last();

    if (metaData.IsRequired)
        labelText += "<span class=\"required-field\">*</span>";

    if (String.IsNullOrEmpty(labelText))
        return MvcHtmlString.Empty;

    var label = new TagBuilder("label");
    label.Attributes.Add("for", helper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(htmlFieldName));

    label.InnerHtml = labelText;
    return MvcHtmlString.Create(label.ToString());
}
13

Utiliser helper pour ajouter une classe de style à l'étiquette

public static MvcHtmlString RequiredLabelFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, object htmlAttributes)
{
    var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
    var resolvedLabelText = metadata.DisplayName ?? metadata.PropertyName;
    if (!metadata.IsRequired)
    {
        return html.LabelFor(expression, resolvedLabelText, htmlAttributes);
    }

    var attributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
    if (attributes == null)
    {
        return html.LabelFor(expression, resolvedLabelText, htmlAttributes);
    }

    const string requiredClass = "required-label";
    if (attributes.ContainsKey("class"))
    {
        var classList = attributes["class"].ToString().Split(' ').ToList();
        classList.Add(requiredClass);
        attributes["class"] = string.Join(" ", classList);
    }
    else
    {
        attributes.Add("class", requiredClass);
    }

    return html.LabelFor(expression, resolvedLabelText, attributes);
}

Ensuite, vous pouvez appeler la classe:

.required-label::after { content : "*" }
3
Daniel Bardi

Je l'ai entravé ensemble à partir d'autres messages:

Cela fonctionne pour moi car le labelfor est suivi d'une entrée plus une étendue (l'entrée est pour l'étiquette et l'étendue de validation)

input[data-val-required]+span:before {
  content: "*";
  font-weight: bold;
  color: red;
  position:relative;
  top:-34px;
  left:-12px;
  font-size:14pt;
}
3
toddmo

Sur la base de la réponse ci-dessus de Renato Saito avec les commentaires, en ajoutant $ (document) .ready et en vérifiant que nous n’ajoutons pas plus d’un astérisque (je reçois cela sur certains de mes champs pour certains raison), j'ai ceci:

// Add asterisks to required fields
$(document).ready(function() {
    $("[data-val-required]").each(function () {
       var label = $('label[for="' + $(this).attr("id") + '"]');
        var asterisksHtml = '<span style="color:red">&nbsp;*</span>';
        if (label.text().length > 0 && label.html().indexOf(asterisksHtml) === -1) {
            label.append(asterisksHtml);
        }
    });
});
1
shlgug

Ajouter une icône de glyphicon décorée après un champ obligatoire (défini via une annotation de données [Obligatoire]) à l'aide d'une extension d'assistance préservant à la fois les étiquettes d'internalisation/traduction et les attributs HTML

1. Créer un dossier "Helpers" et ajouter un nouveau contrôleur "Helper.cs"

using System;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Web.Mvc;

namespace WIPRO.Helpers
{
    public static class Helpers
    {
        public static MvcHtmlString LabelForRequired<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression, string translatedlabelText, object htmlAttributes)
        {
            var metaData = ModelMetadata.FromLambdaExpression(expression, helper.ViewData);

            string htmlFieldName = ExpressionHelper.GetExpressionText(expression);
            string labelText = metaData.DisplayName ?? metaData.PropertyName ?? htmlFieldName.Split('.').Last();

            if (metaData.IsRequired)
            {
                labelText = translatedlabelText + "<span class=\"required\" style=\"color:orange;\"> <span style=\"font-size: 0.4em; vertical-align: super;\" class=\"glyphicon glyphicon-asterisk\" data-unicode=\"270f\"></span></span>";

            }
            else
            {
                labelText = translatedlabelText;

            }

            if (String.IsNullOrEmpty(labelText))
                return MvcHtmlString.Empty;

            var label = new TagBuilder("label");
            label.Attributes.Add("for", helper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(htmlFieldName));

            foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(htmlAttributes))
            {
                label.MergeAttribute(prop.Name.Replace('_', '-'), prop.GetValue(htmlAttributes).ToString(), true);
            }

            label.InnerHtml = labelText;
            return MvcHtmlString.Create(label.ToString());

        }

    }

}

2. A votre avis

@using WIPRO.Helpers

        @Html.LabelForRequired(model => model.Test,"Translated text", htmlAttributes: new { @class = "control-label col-md-2" })

au lieu de  

        @Html.LabelFor(model => model.Test,"Translated text", htmlAttributes: new { @class = "control-label col-md-2" })

J'espère que ça aide ;-)

1
gvth

Le meilleur travail pour moi dans MVC avec plusieurs types de champs

$('input[type=text], input[type=password], input[type=email], input[type=tel], select').each(function () {
    var req = $(this).attr('data-val-required');
    if (undefined != req) {
        var label = $('label[for="' + $(this).attr('name') + '"]');
        var text = label.text();
        if (text.length > 0) {
            label.append('<span style="color:red"> *</span>');
        }
    }
});
0

Bien que cela ne nécessite pas de modifier le LabelFor, c'est le plus simple que je puisse imaginer qui ne nécessite qu'une ligne dans votre ViewModel:

public class FooViewModel
{
   [Required(ErrorMessage = "Name is required")]
   [Display(Name ="Name*")]
   public string Name { get; set; }
}

Html.LabelFor(o => o.Name)
0
ricsierics