web-dev-qa-db-fra.com

Comment ajouter un attribut "obligatoire" à l'éditeur de saisie de texte mvc razor viewmodel

J'ai l'assistant MVC 5 Razor HTML suivant:

@Html.TextBoxFor(m => m.ShortName, 
  new { @class = "form-control", @placeholder = "short name"})

J'ai besoin de ce champ pour être requis (c'est-à-dire avoir un contour rouge lorsque l'utilisateur navigue sans mettre de valeur inn). Dans un WebForms HTML 5, je pourrais simplement dire <input type="text" required /> avoir cet effet. Quelle est la syntaxe appropriée pour accomplir cela dans une syntaxe Razor?

41
Eugene Goldberg

Vous pouvez utiliser l'attribut required html si vous voulez:

@Html.TextBoxFor(m => m.ShortName, 
new { @class = "form-control", placeholder = "short name", required="required"})

ou vous pouvez utiliser la classe RequiredAttribute en .Net. Avec jQuery, RequiredAttribute peut valider du côté serveur et du côté serveur. Si vous souhaitez utiliser la route MVC, je vous conseillerais de lire attribut Annotations de données MVC3 Required .

OR

Vous pouvez être vraiment avancé:

@{
  // if you aren't using UnobtrusiveValidation, don't pass anything to this constructor
  var attributes = new Dictionary<string, object>(
    Html.GetUnobtrusiveValidationAttributes(ViewData.TemplateInfo.HtmlFieldPrefix));

 attributes.Add("class", "form-control");
 attributes.Add("placeholder", "short name");

  if (ViewData.ModelMetadata.ContainerType
      .GetProperty(ViewData.ModelMetadata.PropertyName)
      .GetCustomAttributes(typeof(RequiredAttribute), true)
      .Select(a => a as RequiredAttribute)
      .Any(a => a != null))
  {
   attributes.Add("required", "required");
  }

  @Html.TextBoxFor(m => m.ShortName, attributes)

}

ou si vous en avez besoin pour plusieurs modèles d'éditeur:

public static class ViewPageExtensions
{
  public static IDictionary<string, object> GetAttributes(this WebViewPage instance)
  {
    // if you aren't using UnobtrusiveValidation, don't pass anything to this constructor
    var attributes = new Dictionary<string, object>(
      instance.Html.GetUnobtrusiveValidationAttributes(
         instance.ViewData.TemplateInfo.HtmlFieldPrefix));

    if (ViewData.ModelMetadata.ContainerType
      .GetProperty(ViewData.ModelMetadata.PropertyName)
      .GetCustomAttributes(typeof(RequiredAttribute), true)
      .Select(a => a as RequiredAttribute)
      .Any(a => a != null))
    {
      attributes.Add("required", "required");
    }
  }
}

puis dans vos modèles:

@{
  // if you aren't using UnobtrusiveValidation, don't pass anything to this constructor
  var attributes = this.GetAttributes();

  attributes.Add("class", "form-control");
  attributes.Add("placeholder", "short name");

  @Html.TextBoxFor(m => m.ShortName, attributes)

}

Mise à jour 1 (pour Tomas qui ne connaissent pas ViewData).

Quelle est la différence entre ViewData et ViewBag?

Extrait:

Donc, fondamentalement, il (ViewBag) remplace les chaînes magiques:

ViewData["Foo"]

avec des propriétés magiques:

ViewBag.Foo
76
Erik Philips

Sur votre classe de modèle décorer cette propriété avec [Required] attribut. C'est à dire.:

[Required]
public string ShortName {get; set;}
20
Floremin

Une nouvelle façon de faire cela dans .NET Core consiste à utiliser TagHelpers.

https://docs.Microsoft.com/en-us/aspnet/core/mvc/views/tag-helpers/intro

En vous basant sur ces exemples ( MaxLength , Label ), vous pouvez étendre le TagHelper existant pour répondre à vos besoins.

RequiredTagHelper.cs

using Microsoft.AspNetCore.Razor.TagHelpers;
using System.ComponentModel.DataAnnotations;
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using System.Linq;

namespace ProjectName.TagHelpers
{
    [HtmlTargetElement("input", Attributes = "asp-for")]
    public class RequiredTagHelper : TagHelper
    {
        public override int Order
        {
            get { return int.MaxValue; }
        }

        [HtmlAttributeName("asp-for")]
        public ModelExpression For { get; set; }

        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            base.Process(context, output); 

            if (context.AllAttributes["required"] == null)
            {
                var isRequired = For.ModelExplorer.Metadata.ValidatorMetadata.Any(a => a is RequiredAttribute);
                if (isRequired)
                {
                    var requiredAttribute = new TagHelperAttribute("required");
                    output.Attributes.Add(requiredAttribute);
                }
            }
        }
    }
}

Vous devrez ensuite l'ajouter pour pouvoir l'utiliser dans vos vues:

_ViewImports.cshtml

@using ProjectName
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper "*, ProjectName"

Étant donné le modèle suivant:

Foo.cs

using System;
using System.ComponentModel.DataAnnotations;

namespace ProjectName.Models
{
    public class Foo
    {
        public int Id { get; set; }

        [Required]
        [Display(Name = "Full Name")]
        public string Name { get; set; }
    }
}

et vue (extrait):

New.cshtml

<label asp-for="Name"></label>
<input asp-for="Name"/>

Aboutira à ce code HTML:

<label for="Name">Full Name</label>
<input required type="text" data-val="true" data-val-required="The Full Name field is required." id="Name" name="Name" value=""/>

J'espère que cela sera utile à quiconque ayant la même question mais utilisant .NET Core.

6
bvpb

J'avais besoin de l'attribut HTML5 "requis", alors j'ai fait quelque chose comme ceci:

<%: Html.TextBoxFor(model => model.Name, new { @required = true })%>
2
hestellez

La réponse de @ Erik n'a pas volé pour moi.

Après fait:

 @Html.TextBoxFor(m => m.ShortName,  new { data_val_required = "You need me" })

en plus de le faire manuellement dans le champ, je devais ajouter un conteneur de messages d'erreur

@Html.ValidationMessageFor(m => m.ShortName, null, new { @class = "field-validation-error", data_valmsg_for = "ShortName" })

J'espère que cela vous fait gagner du temps.

0
Matas Vaitkevicius