componentes de entrada de ASP.NET Core Blazor

Nota:

Esta no es la versión más reciente de este artículo. Para la versión actual, consulte la versión .NET 8 de este artículo.

Importante

Esta información hace referencia a un producto en versión preliminar, el cual puede sufrir importantes modificaciones antes de que se publique la versión comercial. Microsoft no proporciona ninguna garantía, expresa o implícita, con respecto a la información proporcionada aquí.

Para la versión actual, consulte la versión .NET 8 de este artículo.

En este artículo, se describen los componentes de entrada integrados de Blazor.

Componentes de entrada

El marco Blazor proporciona componentes de formulario integrados para recibir y validar la entrada del usuario. Los componentes de entrada integrados de la tabla siguiente se admiten en una EditForm con una EditContext.

Los componentes de la tabla también se admiten fuera de un formulario en el marcado de componentes Razor. Las entradas se validan cuando se cambian y cuando un formulario se envía.

Componente de entrada Se representa como…
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> Grupo de componentes InputRadio<TValue> secundarios
InputSelect<TValue> <select>
InputText <input>
InputTextArea <textarea>

Para más información sobre el componente InputFile, vea Cargas de archivo de Blazor en ASP NET Core.

Componente de entrada Se representa como…
InputCheckbox <input type="checkbox">
InputDate<TValue> <input type="date">
InputNumber<TValue> <input type="number">
InputSelect<TValue> <select>
InputText <input>
InputTextArea <textarea>

Nota:

Los componentes InputRadio<TValue> y InputRadioGroup<TValue> están disponibles en ASP.NET Core 5.0 o posteriores. Para más información, seleccione una versión 5.0 o posterior de este artículo.

Todos los componentes de entrada, incluido EditForm, admiten atributos arbitrarios. Cualquier atributo que no coincida con un parámetro de componente se agrega al elemento HTML representado.

Los componentes de entrada proporcionan un comportamiento predeterminado para validar cuando se cambia un campo:

  • En el caso de los componentes de entrada de un formulario con EditContext, el comportamiento de validación predeterminado incluye actualizar la clase CSS de campo para reflejar el estado del campo como válido o no válido con el estilo de validación del elemento HTML subyacente.
  • Para los controles que no tienen un EditContext, la validación predeterminada refleja el estado válido o no válido, pero no proporciona estilos de validación al elemento HTML subyacente.

Algunos componentes incluyen lógica de análisis de utilidad. Así, por ejemplo, InputDate<TValue> y InputNumber<TValue> tratan los valores no analizables sin problemas registrándolos como errores de validación. Los tipos con capacidad para aceptar valores nulos también admiten la nulabilidad del campo de destino (por ejemplo, int? para un entero que admite un valor NULL).

Para más información sobre el componente InputFile, vea Cargas de archivo de Blazor en ASP NET Core.

Formulario de ejemplo

El siguiente Starship tipo, que se usa en varios de los ejemplos y ejemplos de este artículo en otros artículos de nodos de Forms , define un conjunto diverso de propiedades con anotaciones de datos:

  • Id se requiere porque se anota con RequiredAttribute. Id requiere un valor de al menos un carácter, pero no más de 16 caracteres mediante StringLengthAttribute.
  • Description es opcional porque no se anota con RequiredAttribute.
  • Classification es obligatorio.
  • El valor predeterminado de la propiedad MaximumAccommodation es cero, pero requiere un valor de uno a 100 000 por su RangeAttribute.
  • IsValidatedDesign requiere que la propiedad tenga un valor true, que coincide con un estado seleccionado cuando la propiedad está enlazada a una casilla en la interfaz de usuario (<input type="checkbox">).
  • ProductionDate es un objeto DateTime y es obligatorio.

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

El siguiente formulario acepta y valida la entrada del usuario mediante lo siguiente:

  • Propiedades y validación definidas en el modelo Starship anterior.
  • Varios de los componentes de entrada incorporados en Blazor.

Cuando se establece la propiedad del modelo para la clasificación del barco (Classification), se comprueba la opción que coincide con el modelo. Por ejemplo, checked="@(Model!.Classification == "Exploration")" para la clasificación de un barco de exploración. El motivo de establecer explícitamente la opción activada es que el valor de un elemento <select> solo está presente en el explorador. Si el formulario se representa en el servidor después de enviarlo, cualquier estado del cliente se invalida con el estado del servidor, que normalmente no marca una opción como activada. Al establecer la opción activada desde la propiedad del modelo, la clasificación siempre refleja el estado del modelo. Esto conserva la selección de clasificación en los envíos de formularios que dan como resultado la nueva representación de formularios en el servidor. En situaciones en las que el formulario no se vuelve a representar en el servidor, como cuando el modo de representación del servidor interactivo se aplica directamente al componente, no es necesaria la asignación explícita de la opción activada del modelo, porque Blazor conserva el estado para el elemento <select> en el cliente.

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

El componente EditForm del ejemplo anterior crea un objeto EditContext basado en la instancia Starship asignada (Model="...") y controla un formulario válido. En el ejemplo siguiente se muestra cómo asignar un componente EditContext a un formulario y validar cuándo se envía el formulario.

En el ejemplo siguiente:

  • Se usa una versión abreviada del formulario Starfleet Starship Database anterior (componente Starship3) que solo acepta un valor para el identificador de Starship. Las demás propiedades Starship reciben valores predeterminados válidos cuando se crea una instancia del tipo Starship.
  • El método Submit se ejecuta cuando se selecciona el botón Submit.
  • El formulario se valida mediante una llamada a EditContext.Validate en el método Submit.
  • El código adicional se ejecuta según el resultado de la validación.

Nota

Submit en el ejemplo siguiente se muestra como un método asincrónico porque el almacenamiento de valores de formulario a menudo usa llamadas asincrónicas (await ...). Si el formulario se usa en una aplicación de prueba, tal como se muestra, Submit simplemente se ejecuta sincrónicamente. Con fines de prueba, ignore la siguiente advertencia de compilación:

This async method lacks 'await' operators and will run synchronously (Program.cs(77,44): advertencia CS1998: este método asincrónico carece de operadores "await" y se ejecutará de manera sincrónica). ...

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

Nota:

No se admite el cambio de EditContext después de su asignación.

Selección de varias opciones con el componente InputSelect

El enlace admite la selección de la opción multiple con el componente InputSelect<TValue>. El evento @onchange proporciona una matriz de las opciones seleccionadas mediante argumentos de evento (ChangeEventArgs). El valor se debe enlazar a un tipo de matriz y el enlace a un tipo de matriz hace que el atributo multiple sea opcional en la etiqueta InputSelect<TValue>.

En el ejemplo siguiente, el usuario debe seleccionar al menos dos clasificaciones de Starship, pero no más de tres.

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

Para obtener información sobre cómo se controlan las cadenas vacías y los valores null en el enlace de datos, vea la sección Enlace de opciones de InputSelect a valores null de objetos de C#.

Enlace de opciones de InputSelect a valores null de objetos de C#

Para obtener información sobre cómo se controlan las cadenas vacías y los valores null en el enlace de datos, vea Enlace de datos de Blazor en ASP NET.Core.

Compatibilidad con nombres para mostrar

Varios componentes integrados admiten nombres para mostrar con el parámetro InputBase<TValue>.DisplayName.

En el formulario Starfleet Starship Database (componente Starship3) de la sección Formulario de ejemplo, la fecha de producción de un nuevo objeto Starship no especifica un nombre para mostrar:

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

Si el campo contiene una fecha no válida cuando se envía el formulario, el mensaje de error no muestra un nombre descriptivo. El nombre del campo "ProductionDate" no tiene un espacio entre "Production" y "Date" cuando aparece en el resumen de validación:

El campo ProductionDate debe ser una fecha.

Establezca la propiedad DisplayName en un nombre descriptivo con un espacio entre las palabras "Production" y "Date":

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

El resumen de validación muestra el nombre descriptivo cuando el valor del campo no es válido:

El campo Fecha de producción debe ser una fecha.

Compatibilidad con plantillas de mensaje de error

InputDate<TValue> y InputNumber<TValue> admiten plantillas de mensaje de error:

En el formulario Starfleet Starship Database (componente Starship3) de la sección Formulario de ejemplo con un nombre para mostrar descriptivo asignado, el campo Production Date genera un mensaje de error mediante la siguiente plantilla de mensaje de error predeterminada:

The {0} field must be a date.

La posición del marcador de posición {0} es donde aparece el valor de la propiedad DisplayName cuando se muestra el error al usuario.

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

El campo Fecha de producción debe ser una fecha.

Asigne una plantilla personalizada a ParsingErrorMessage para proporcionar un mensaje personalizado:

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

El campo Fecha de producción tiene un valor de fecha incorrecto.

En el formulario Starfleet Starship Database (componente Starship3) de la sección Formulario de ejemplo se usa una plantilla de mensaje de error predeterminada:

The {0} field must be a date.

La posición del marcador de posición {0} es donde aparece el valor de la propiedad DisplayName cuando se muestra el error al usuario.

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

El campo ProductionDate debe ser una fecha.

Asigne una plantilla personalizada a ParsingErrorMessage para proporcionar un mensaje personalizado:

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

El campo ProductionDate tiene un valor de fecha incorrecto.