Composants d’entrée Blazor ASP.NET Core

Remarque

Ceci n’est pas la dernière version de cet article. Pour la version actuelle, consultez la version .NET 8 de cet article.

Important

Ces informations portent sur la préversion du produit, qui est susceptible d’être en grande partie modifié avant sa commercialisation. Microsoft n’offre aucune garantie, expresse ou implicite, concernant les informations fournies ici.

Pour la version actuelle, consultez la version .NET 8 de cet article.

Cet article décrit les composants d’entrée intégrés de Blazor.

Composants d’entrée

L’infrastructure Blazor fournit des composants d’entrée intégrés pour recevoir et valider les entrées utilisateur. Les composants d’entrée intégrés dans le tableau suivant sont pris en charge dans un EditForm avec un EditContext.

Les composants du tableau sont également pris en charge en dehors d’un formulaire dans la balise de composant Razor. Les entrées sont validées lorsqu’elles sont modifiées et lorsqu’un formulaire est envoyé.

Composant d’entrée Rendu comme suit…
InputCheckbox <input type="checkbox">
InputDate<TValue> <input type="date">
InputFile <input type="file">
InputNumber<TValue> <input type="number">
InputRadio<TValue> <input type="radio">
InputRadioGroup<TValue> Groupe d’enfants InputRadio<TValue>
InputSelect<TValue> <select>
InputText <input>
InputTextArea <textarea>

Pour plus d’informations sur le composant InputFile, consultez Téléchargements de fichiers Blazor ASP.NET Core.

Composant d’entrée Rendu comme suit…
InputCheckbox <input type="checkbox">
InputDate<TValue> <input type="date">
InputNumber<TValue> <input type="number">
InputSelect<TValue> <select>
InputText <input>
InputTextArea <textarea>

Remarque

Les composants InputRadio<TValue> et InputRadioGroup<TValue> sont disponibles dans ASP.NET Core 5.0 ou version ultérieure. Pour plus d’informations, sélectionnez une version 5.0 ou ultérieure de cet article.

Tous les composants d’entrée, y compris EditForm, prennent en charge les attributs arbitraires. Tout attribut qui ne correspond pas à un paramètre de composant est ajouté à l’élément HTML rendu.

Les composants d’entrée fournissent un comportement par défaut pour la validation lorsqu’un champ est modifié :

  • Pour les composants d’entrée dans un formulaire avec un EditContext, le comportement de validation par défaut comprend la mise à jour de la classe CSS de champ pour refléter l’état du champ comme valide ou non valide avec le style de validation de l’élément HTML sous-jacent.
  • Pour les contrôles qui n’ont pas de EditContext, la validation par défaut reflète l’état valide ou non valide, mais ne fournit pas de style de validation à l’élément HTML sous-jacent.

Certains composants incluent une logique d’analyse utile. Par exemple, InputDate<TValue> et InputNumber<TValue> gèrent correctement les valeurs non analysables en inscrivant les valeurs non analysables en tant qu’erreurs de validation. Les types qui peuvent accepter des valeurs nulles prennent également en charge la possibilité de valeur nulle du champ cible (par exemple, int? pour un entier pouvant accepter la valeur Null).

Pour plus d’informations sur le composant InputFile, consultez Téléchargements de fichiers Blazor ASP.NET Core.

Exemple de formulaire

Le type Starship suivant , qui est utilisé dans plusieurs exemples de cet article et dans des exemples d’autres articles du nœud Formulaires, définit un ensemble diversifié de propriétés avec des annotations de données :

  • Id est requis, car il est annoté avec le RequiredAttribute. Id nécessite une valeur d’au moins un caractère, mais pas plus de 16 caractères à l’aide du StringLengthAttribute.
  • Description est facultatif, car il n’est pas annoté avec le RequiredAttribute.
  • Classification est obligatoire.
  • La propriété MaximumAccommodation a la valeur zéro par défaut, mais nécessite une valeur comprise entre un et 100 000 par son RangeAttribute.
  • IsValidatedDesign exige que la propriété ait une valeur true, qui correspond à un état sélectionné lorsque la propriété est liée à une case à cocher dans l’interface utilisateur (<input type="checkbox">).
  • ProductionDate est un DateTime et est obligatoire.

Starship.cs:

using System.ComponentModel.DataAnnotations;

namespace BlazorSample;

public class Starship
{
    [Required]
    [StringLength(16, ErrorMessage = "Identifier too long (16 character limit).")]
    public string? Id { get; set; }

    public string? Description { get; set; }

    [Required]
    public string? Classification { get; set; }

    [Range(1, 100000, ErrorMessage = "Accommodation invalid (1-100000).")]
    public int MaximumAccommodation { get; set; }

    [Required]
    [Range(typeof(bool), "true", "true", ErrorMessage = "Approval required.")]
    public bool IsValidatedDesign { get; set; }

    [Required]
    public DateTime ProductionDate { get; set; }
}
using System.ComponentModel.DataAnnotations;

public class Starship
{
    [Required]
    [StringLength(16, ErrorMessage = "Identifier too long (16 character limit).")]
    public string? Id { get; set; }

    public string? Description { get; set; }

    [Required]
    public string? Classification { get; set; }

    [Range(1, 100000, ErrorMessage = "Accommodation invalid (1-100000).")]
    public int MaximumAccommodation { get; set; }

    [Required]
    [Range(typeof(bool), "true", "true", 
        ErrorMessage = "This form disallows unapproved ships.")]
    public bool IsValidatedDesign { get; set; }

    [Required]
    public DateTime ProductionDate { get; set; }
}
using System.ComponentModel.DataAnnotations;

public class Starship
{
    [Required]
    [StringLength(16, ErrorMessage = "Identifier too long (16 character limit).")]
    public string? Id { get; set; }

    public string? Description { get; set; }

    [Required]
    public string? Classification { get; set; }

    [Range(1, 100000, ErrorMessage = "Accommodation invalid (1-100000).")]
    public int MaximumAccommodation { get; set; }

    [Required]
    [Range(typeof(bool), "true", "true", 
        ErrorMessage = "This form disallows unapproved ships.")]
    public bool IsValidatedDesign { get; set; }

    [Required]
    public DateTime ProductionDate { get; set; }
}
using System;
using System.ComponentModel.DataAnnotations;

public class Starship
{
    [Required]
    [StringLength(16, ErrorMessage = "Identifier too long (16 character limit).")]
    public string Id { get; set; }

    public string Description { get; set; }

    [Required]
    public string Classification { get; set; }

    [Range(1, 100000, ErrorMessage = "Accommodation invalid (1-100000).")]
    public int MaximumAccommodation { get; set; }

    [Required]
    [Range(typeof(bool), "true", "true", 
        ErrorMessage = "This form disallows unapproved ships.")]
    public bool IsValidatedDesign { get; set; }

    [Required]
    public DateTime ProductionDate { get; set; }
}
using System;
using System.ComponentModel.DataAnnotations;

public class Starship
{
    [Required]
    [StringLength(16, ErrorMessage = "Identifier too long (16 character limit).")]
    public string Id { get; set; }

    public string Description { get; set; }

    [Required]
    public string Classification { get; set; }

    [Range(1, 100000, ErrorMessage = "Accommodation invalid (1-100000).")]
    public int MaximumAccommodation { get; set; }

    [Required]
    [Range(typeof(bool), "true", "true", 
        ErrorMessage = "This form disallows unapproved ships.")]
    public bool IsValidatedDesign { get; set; }

    [Required]
    public DateTime ProductionDate { get; set; }
}

Le formulaire suivant accepte et valide l’entrée utilisateur à l’aide de :

  • Les propriétés et la validation définies dans le modèle Starship précédent.
  • Plusieurs des composants d’entrée intégrés de Blazor.

Lorsque la propriété du modèle pour la classification du vaisseau (Classification) est définie, l’option correspondant au modèle est cochée. Par exemple, checked="@(Model!.Classification == "Exploration")" pour la classification d’un vaisseau d’exploration. La raison pour laquelle l’option cochée est définie de manière explicite est que la valeur d’un élément <select> n’est présente que dans le navigateur. Si le formulaire est affiché sur le serveur après sa soumission, tout état du client est remplacé par l’état du serveur, ce qui n’entraîne généralement pas le marquage d’une option comme cochée. Le fait de définir l’option cochée à partir de la propriété du modèle permet à la classification de toujours refléter l’état du modèle. La sélection de la classification est donc conservée entre les soumissions de formulaire qui entraînent un nouvel affichage du formulaire sur le serveur. Dans les situations où le formulaire n’est pas affiché à nouveau sur le serveur, par exemple lorsque le mode d’affichage Serveur interactif est appliqué directement au composant, l’affectation explicite de l’option cochée à partir du modèle n’est pas nécessaire, car elle Blazor préserve l’état de <select> l’élément sur le client.

Starship3.razor:

@page "/starship-3"
@inject ILogger<Starship3> Logger

<h1>Starfleet Starship Database</h1>

<h2>New Ship Entry Form</h2>

<EditForm Model="Model" OnValidSubmit="Submit" FormName="Starship3">
    <DataAnnotationsValidator />
    <ValidationSummary />
    <div>
        <label>
            Identifier: 
            <InputText @bind-Value="Model!.Id" />
        </label>
    </div>
    <div>
        <label>
            Description (optional): 
            <InputTextArea @bind-Value="Model!.Description" />
        </label>
    </div>
    <div>
        <label>
            Primary Classification: 
            <InputSelect @bind-Value="Model!.Classification">
                <option value="">
                    Select classification ...
                </option>
                <option checked="@(Model!.Classification == "Exploration")" 
                    value="Exploration">
                    Exploration
                </option>
                <option checked="@(Model!.Classification == "Diplomacy")" 
                    value="Diplomacy">
                    Diplomacy
                </option>
                <option checked="@(Model!.Classification == "Defense")" 
                    value="Defense">
                    Defense
                </option>
            </InputSelect>
        </label>
    </div>
    <div>
        <label>
            Maximum Accommodation: 
            <InputNumber @bind-Value="Model!.MaximumAccommodation" />
        </label>
    </div>
    <div>
        <label>
            Engineering Approval: 
            <InputCheckbox @bind-Value="Model!.IsValidatedDesign" />
        </label>
    </div>
    <div>
        <label>
            Production Date: 
            <InputDate @bind-Value="Model!.ProductionDate" />
        </label>
    </div>
    <div>
        <button type="submit">Submit</button>
    </div>
</EditForm>

@code {
    [SupplyParameterFromForm]
    private Starship? Model { get; set; }

    protected override void OnInitialized() =>
        Model ??= new() { ProductionDate = DateTime.UtcNow };

    private void Submit()
    {
        Logger.LogInformation("Id = {Id} Description = {Description} " +
            "Classification = {Classification} MaximumAccommodation = " +
            "{MaximumAccommodation} IsValidatedDesign = " +
            "{IsValidatedDesign} ProductionDate = {ProductionDate}",
            Model?.Id, Model?.Description, Model?.Classification,
            Model?.MaximumAccommodation, Model?.IsValidatedDesign,
            Model?.ProductionDate);
    }
}
@page "/starship-3"
@inject ILogger<Starship3> Logger

<h1>Starfleet Starship Database</h1>

<h2>New Ship Entry Form</h2>

<EditForm Model="Model" OnValidSubmit="Submit">
    <DataAnnotationsValidator />
    <ValidationSummary />
    <div>
        <label>
            Identifier:
            <InputText @bind-Value="Model!.Id" />
        </label>
    </div>
    <div>
        <label>
            Description (optional):
            <InputTextArea @bind-Value="Model!.Description" />
        </label>
    </div>
    <div>
        <label>
            Primary Classification:
            <InputSelect @bind-Value="Model!.Classification">
                <option value="">Select classification ...</option>
                <option value="Exploration">Exploration</option>
                <option value="Diplomacy">Diplomacy</option>
                <option value="Defense">Defense</option>
            </InputSelect>
        </label>
    </div>
    <div>
        <label>
            Maximum Accommodation:
            <InputNumber @bind-Value="Model!.MaximumAccommodation" />
        </label>
    </div>
    <div>
        <label>
            Engineering Approval:
            <InputCheckbox @bind-Value="Model!.IsValidatedDesign" />
        </label>
    </div>
    <div>
        <label>
            Production Date:
            <InputDate @bind-Value="Model!.ProductionDate" />
        </label>
    </div>
    <div>
        <button type="submit">Submit</button>
    </div>
</EditForm>

@code {
    private Starship? Model { get; set; }

    protected override void OnInitialized() =>
        Model ??= new() { ProductionDate = DateTime.UtcNow };

    private void Submit()
    {
        Logger.LogInformation("Id = {Id} Description = {Description} " +
            "Classification = {Classification} MaximumAccommodation = " +
            "{MaximumAccommodation} IsValidatedDesign = " +
            "{IsValidatedDesign} ProductionDate = {ProductionDate}", 
            Model?.Id, Model?.Description, Model?.Classification, 
            Model?.MaximumAccommodation, Model?.IsValidatedDesign, 
            Model?.ProductionDate);
    }
}

Le EditForm dans l’exemple précédent crée un EditContext basé sur l’instance de Starship affectée (Model="...") et gère un formulaire valide. L’exemple suivant montre comment affecter un EditContext à un formulaire et valider la soumission du formulaire.

Dans l’exemple suivant :

  • Une version abrégée du formulaire Starfleet Starship Database précédent (composant Starship3) est utilisée et n’accepte qu’une valeur pour l’ID du navire. Les autres propriétés Starship reçoivent des valeurs par défaut valides lorsqu’une instance du type Starship est créée.
  • La méthode Submit s’exécute lorsque le bouton Submit est sélectionné.
  • Le formulaire est validé en appelant EditContext.Validate dans la méthode Submit.
  • La journalisation est exécutée en fonction du résultat de la validation.

Remarque

Submit est démontré (dans l’exemple suivant) comme une méthode asynchrone, car le stockage des valeurs de formulaire utilise souvent des appels asynchrones (await ...). Si le formulaire est utilisé dans une application de test comme indiqué, Submit s’exécute simplement de manière synchrone. À des fins de test, ignorez l’avertissement de build suivant :

Cette méthode async n’a pas d’opérateur ’await’ et elle va s’exécute de façon synchrone. ...

Starship4.razor:

@page "/starship-4"
@inject ILogger<Starship4> Logger

<EditForm EditContext="editContext" OnSubmit="Submit" FormName="Starship4">
    <DataAnnotationsValidator />
    <div>
        <label>
            Identifier: 
            <InputText @bind-Value="Model!.Id" />
        </label>
    </div>
    <div>
        <button type="submit">Submit</button>
    </div>
</EditForm>

@code {
    private EditContext? editContext;

    [SupplyParameterFromForm]
    private Starship? Model { get; set; }

    protected override void OnInitialized()
    {
        Model ??=
            new()
                {
                    Id = "NCC-1701",
                    Classification = "Exploration",
                    MaximumAccommodation = 150,
                    IsValidatedDesign = true,
                    ProductionDate = new DateTime(2245, 4, 11)
                };
        editContext = new(Model);
    }

    private async Task Submit()
    {
        if (editContext != null && editContext.Validate())
        {
            Logger.LogInformation("Submit called: Form is valid");

            // await ...
        }
        else
        {
            Logger.LogInformation("Submit called: Form is INVALID");
        }
    }
}
@page "/starship-4"
@inject ILogger<Starship4> Logger

<EditForm EditContext="editContext" OnSubmit="Submit">
    <DataAnnotationsValidator />
    <div>
        <label>
            Identifier:
            <InputText @bind-Value="Model!.Id" />
        </label>
    </div>
    <div>
        <button type="submit">Submit</button>
    </div>
</EditForm>

@code {
    private EditContext? editContext;

    private Starship Model { get; set; }

    protected override void OnInitialized()
    {
        Model ??= 
            new()
            {
                Id = "NCC-1701",
                Classification = "Exploration",
                MaximumAccommodation = 150,
                IsValidatedDesign = true,
                ProductionDate = new DateTime(2245, 4, 11)
            };
        editContext = new(Model);
    }

    private async Task Submit()
    {
        if (editContext != null && editContext.Validate())
        {
            Logger.LogInformation("Submit called: Form is valid");

            // await ...
        }
        else
        {
            Logger.LogInformation("Submit called: Form is INVALID");
        }
    }
}

Remarque

La modification du EditContext après son affectation n’est pas prise en charge.

Sélection de plusieurs options avec le composant InputSelect

La liaison prend en charge la sélection d’options multiple avec le composant InputSelect<TValue>. L’événement @onchange fournit un tableau des options sélectionnées via des arguments d’événement (ChangeEventArgs). La valeur doit être liée à un type de tableau, et la liaison à un type de tableau rend l’attribut multiple facultatif sur la balise InputSelect<TValue>.

Dans l’exemple suivant, l’utilisateur doit sélectionner au moins deux classifications de vaisseaux, mais pas plus de trois classifications.

Starship5.razor:

@page "/starship-5"
@using System.ComponentModel.DataAnnotations
@inject ILogger<Starship5> Logger

<h1>Bind Multiple <code>InputSelect</code> Example</h1>

<EditForm EditContext="editContext" OnValidSubmit="Submit" FormName="Starship5">
    <DataAnnotationsValidator />
    <ValidationSummary />
    <div>
        <label>
            Select classifications (Minimum: 2, Maximum: 3):
            <InputSelect @bind-Value="Model!.SelectedClassification">
                <option value="@Classification.Exploration">Exploration</option>
                <option value="@Classification.Diplomacy">Diplomacy</option>
                <option value="@Classification.Defense">Defense</option>
                <option value="@Classification.Research">Research</option>
            </InputSelect>
        </label>
    </div>
    <div>
        <button type="submit">Submit</button>
    </div>
</EditForm>

@if (Model?.SelectedClassification?.Length > 0)
{
    <div>@string.Join(", ", Model.SelectedClassification)</div>
}

@code {
    private EditContext? editContext;

    [SupplyParameterFromForm]
    private Starship? Model { get; set; }

    protected override void OnInitialized()
    {
        Model = new();
        editContext = new(Model);
    }

    private void Submit()
    {
        Logger.LogInformation("Submit called: Processing the form");
    }

    private class Starship
    {
        [Required]
        [MinLength(2, ErrorMessage = "Select at least two classifications.")]
        [MaxLength(3, ErrorMessage = "Select no more than three classifications.")]
        public Classification[]? SelectedClassification { get; set; } =
            new[] { Classification.None };
    }

    private enum Classification { None, Exploration, Diplomacy, Defense, Research }
}
@page "/starship-5"
@using System.ComponentModel.DataAnnotations
@inject ILogger<Starship5> Logger

<h1>Bind Multiple <code>InputSelect</code> Example</h1>

<EditForm EditContext="editContext" OnValidSubmit="Submit">
    <DataAnnotationsValidator />
    <ValidationSummary />
    <div>
        <label>
            Select classifications (Minimum: 2, Maximum: 3):
            <InputSelect @bind-Value="Model!.SelectedClassification">
                <option value="@Classification.Exploration">Exploration</option>
                <option value="@Classification.Diplomacy">Diplomacy</option>
                <option value="@Classification.Defense">Defense</option>
                <option value="@Classification.Research">Research</option>
            </InputSelect>
        </label>
    </div>
    <div>
        <button type="submit">Submit</button>
    </div>
</EditForm>

@if (Model?.SelectedClassification?.Length > 0)
{
    <div>@string.Join(", ", Model.SelectedClassification)</div>
}

@code {
    private EditContext? editContext;

    private Starship? Model { get; set; }

    protected override void OnInitialized()
    {
        Model ??= new();
        editContext = new(Model);
    }

    private void Submit()
    {
        Logger.LogInformation("Submit called: Processing the form");
    }

    private class Starship
    {
        [Required]
        [MinLength(2, ErrorMessage = "Select at least two classifications.")]
        [MaxLength(3, ErrorMessage = "Select no more than three classifications.")]
        public Classification[]? SelectedClassification { get; set; } =
            new[] { Classification.None };
    }

    private enum Classification { None, Exploration, Diplomacy, Defense, Research }
}

Pour plus d’informations sur la façon dont les chaînes et les valeurs null vides sont gérées dans la liaison de données, consultez la section Options InputSelect de liaison à des valeurs null d’objet C#.

Options InputSelect de liaison aux valeurs null d’objet C#

Pour plus d’informations sur la façon dont les chaînes et les valeurs null vides sont gérées dans la liaison de données, consultez Liaison de données Blazor ASP.NET Core.

Prise en charge des noms d’affichage

Plusieurs composants intégrés prennent en charge les noms d’affichage avec le paramètre InputBase<TValue>.DisplayName.

Dans le formulaire Starfleet Starship Database (composant Starship3) de la section Exemple de formulaire, la date de production d’un nouveau vaisseau ne spécifie pas de nom d’affichage :

<label>
    Production Date:
    <InputDate @bind-Value="Model!.ProductionDate" />
</label>

Si le champ contient une date non valide lors de l’envoi du formulaire, le message d’erreur n’affiche pas de nom convivial. Le nom de champ, « ProductionDate » n’a pas d’espace entre « Production » et « Date » lorsqu’il s’affiche dans le résumé de validation :

Le champ ProductionDate doit être une date.

Définissez la propriété DisplayName sur un nom convivial avec un espace entre les mots « Production » et « Date » :

<label>
    Production Date:
    <InputDate @bind-Value="Model!.ProductionDate" 
        DisplayName="Production Date" />
</label>

Le résumé de validation affiche le nom convivial lorsque la valeur du champ n’est pas valide :

Le champ Date de production doit être une date.

Prise en charge du modèle de message d’erreur

InputDate<TValue> et InputNumber<TValue> prennent en charge les modèles de message d’erreur :

Dans le formulaire Starfleet Starship Database (composant Starship3) de la section Exemple de formulaire avec un nom d’affichage convivial affecté, le champ Production Date génère un message d’erreur à l’aide du modèle de message d’erreur par défaut suivant :

The {0} field must be a date.

La position de l’espace réservé {0} correspond à l’emplacement où la valeur de la propriété DisplayName s’affiche lorsque l’erreur est affichée à l’utilisateur.

<label>
    Production Date:
    <InputDate @bind-Value="Model!.ProductionDate" 
        DisplayName="Production Date" />
</label>

Le champ Date de production doit être une date.

Affectez un modèle personnalisé à ParsingErrorMessage pour fournir un message personnalisé :

<label>
    Production Date:
    <InputDate @bind-Value="Model!.ProductionDate" 
        DisplayName="Production Date" 
        ParsingErrorMessage="The {0} field has an incorrect date value." />
</label>

Le champ Date de production a une valeur de date incorrecte.

Dans le formulaire Starfleet Starship Database (composant Starship3) de la section Exemple de formulaire, un modèle de message d’erreur par défaut est utilisé :

The {0} field must be a date.

La position de l’espace réservé {0} correspond à l’emplacement où la valeur de la propriété DisplayName s’affiche lorsque l’erreur est affichée à l’utilisateur.

<label>
    Production Date:
    <InputDate @bind-Value="Model!.ProductionDate" />
</label>

Le champ ProductionDate doit être une date.

Affectez un modèle personnalisé à ParsingErrorMessage pour fournir un message personnalisé :

<label>
    Production Date:
    <InputDate @bind-Value="Model!.ProductionDate" 
        ParsingErrorMessage="The {0} field has an incorrect date value." />
</label>

Le champ ProductionDate a une valeur de date incorrecte.