it-swarm.dev

Jak mogę zmodyfikować LabelFor, aby wyświetlić gwiazdkę na wymaganych polach?

Chcę utworzyć metodę rozszerzenia dla zmiennej HtmlHelper, która pozwala mi utworzyć zmienną LabelFor właściwość wyświetla po niej gwiazdkę, jeśli jest to pole wymagane. Jak mogę to zrobić?

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

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

Oto wpis na blogu który opisuje, jak to zrobić.

Aby dać ci mały przykład zmodyfikowany z powyższej strony (uwaga - nie skompilowałem/nie przetestowałem tego):

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

Możesz dodać gwiazdkę do wymaganego pola wyłącznie poprzez CSS.

Najpierw utwórz dla niego klasę CSS:

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

Spowoduje to dołączenie czerwonej gwiazdki do dowolnego elementu z „wymaganą” klasą.

Następnie, twoim zdaniem, po prostu dodaj nową klasę do etykiety:

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

Jeszcze lepszy może być niestandardowy Pomocnik HTML, który rozpoznaje, czy pole ma atrybut [Wymagany], a jeśli tak, dodaje klasę CSS required.

113
Roger Rouse

Zrobiłem tak, ponieważ moje wymagane pola muszą być dynamiczne (zdefiniowane w pliku konfiguracyjnym)

Dodaj na końcu widoku:

    <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

Oto moje rozwiązanie oparte na odpowiedzi Adama Tulipera ale zmodyfikowane do pracy z Bootstrap i pozwalające na użycie niestandardowych atrybutów.

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

}

Następnie nazywam to z mojego punktu widzenia w ten sposób:

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

P.S. Upewnij się, że nie zapomnisz dołączyć swojej przestrzeni nazw do swojego widoku.

19
Maxime

zobacz ten wpis tutaj - powinien zawierać większość tego, czego potrzebujesz 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

Użyj pomocnika, aby dodać klasę stylu do etykiety

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

Następnie możesz stylizować klasę:

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

Pocieszałem to razem z innych postów:

Działa dla mnie, ponieważ po etykiecie znajduje się wejście plus zakres (wejście, dla którego jest etykieta i zakres sprawdzania poprawności)

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

Opierając się na powyższej odpowiedzi Renato Saito wraz z komentarzami, a także dodając $ (dokument) .ready i sprawdzając, czy nie dodajemy więcej niż jednej gwiazdki (dla niektórych z nich dodałem ją powód), mam to:

// 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

Dodaj ozdobną ikonę glyphicon po obowiązkowym polu (zdefiniowanym za pomocą adnotacji danych [Wymagane]) za pomocą rozszerzenia pomocnika zachowującego zarówno etykiety internalizacji/tłumaczenia, jak i atrybuty html

1. Utwórz folder „Pomocnicy” i dodaj nowy kontroler „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. W Twojej opinii

@using WIPRO.Helpers

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

zamiast  

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

Mam nadzieję, że to pomoże ;-)

1
gvth

Najlepsza praca dla mnie w MVC z wieloma typami pól

$('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>');
        }
    }
});

Chociaż nie wymaga to modyfikacji LabelFor, jest to najprostszy, o którym myślę, który wymaga tylko 1 linii w ViewModelu:

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

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