Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 89 additions & 1 deletion aspnetcore/blazor/components/data-binding.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,94 @@ Razor attribute binding is case sensitive:
* `@bind` and `@bind:event` are valid.
* `@Bind`/`@Bind:Event` (capital letters `B` and `E`) or `@BIND`/`@BIND:EVENT` (all capital letters) **are invalid**.

::: moniker range=">= aspnetcore-6.0"

## Multiple option selection with `<input>` elements

*This feature applies to ASP.NET Core 6.0 Preview 7 or later. ASP.NET Core 6.0 is scheduled for release later this year.*

Binding supports [`multiple`](https://developer.mozilla.org/docs/Web/HTML/Attributes/multiple) option selection with `<input>` elements. The [`@onchange`](xref:mvc/views/razor#onevent) event provides an array of the selected elements via [event arguments (`ChangeEventArgs`)](xref:blazor/components/event-handling#event-arguments). The value must be bound to an array type.

`Pages/BindMultipleInput.razor`:

```razor
@page "/bind-multiple-input"

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

<p>
<label>
Select one or more cars:
<select @onchange="SelectedCarsChanged" multiple>
<option value="audi">Audi</option>
<option value="jeep">Jeep</option>
<option value="opel">Opel</option>
<option value="saab">Saab</option>
<option value="volvo">Volvo</option>
</select>
</label>
</p>

<p>
Selected Cars: @string.Join(", ", SelectedCars)
</p>

<p>
<label>
Select one or more cities:
<select @bind="SelectedCities" multiple>
<option value="bal">Baltimore</option>
<option value="la">Los Angeles</option>
<option value="pdx">Portland</option>
<option value="sf">San Francisco</option>
<option value="sea">Seattle</option>
</select>
</label>
</p>

<span>
Selected Cities: @string.Join(", ", SelectedCities)
</span>

@code {
public string[] SelectedCars { get; set; } = new string[] { };
public string[] SelectedCities { get; set; } = new[] { "bal", "sea" };

void SelectedCarsChanged(ChangeEventArgs e)
{
SelectedCars = (string[])e.Value;
}
}
```

For information on how empty strings and `null` values are handled in data binding, see the [Binding `<select>` element options to C# object `null` values](#binding-select-element-options-to-c-object-null-values) section.

::: moniker-end

## Binding `<select>` element options to C# object `null` values

There's no sensible way to represent a `<select>` element option value as a C# object `null` value, because:

* HTML attributes can't have `null` values. The closest equivalent to `null` in HTML is absence of the HTML `value` attribute from the `<option>` element.
* When selecting an `<option>` with no `value` attribute, the browser treats the value as the *text content* of that `<option>`'s element.

The Blazor framework doesn't attempt to suppress the default behavior because it would involve:

* Creating a chain of special-case workarounds in the framework.
* Breaking changes to current framework behavior.

::: moniker range=">= aspnetcore-5.0"

The most plausible `null` equivalent in HTML is an *empty string* `value`. The Blazor framework handles `null` to empty string conversions for two-way binding to a `<select>`'s value.

::: moniker-end

::: moniker range="< aspnetcore-5.0"

The Blazor framework doesn't automatically handle `null` to empty string conversions when attempting two-way binding to a `<select>`'s value. For more information, see [Fix binding `<select>` to a null value (dotnet/aspnetcore #23221)](https://github.com/dotnet/aspnetcore/pull/23221).

::: moniker-end

## Unparsable values

When a user provides an unparsable value to a databound element, the unparsable value is automatically reverted to its previous value when the bind event is triggered.
Expand Down Expand Up @@ -325,5 +413,5 @@ For an alternative approach suited to sharing data in memory and across componen

* <xref:blazor/forms-validation>
* [Binding to radio buttons in a form](xref:blazor/forms-validation#radio-buttons)
* [Binding `<select>` element options to C# object `null` values in a form](xref:blazor/forms-validation#binding-select-element-options-to-c-object-null-values)
* [Binding `InputSelect` options to C# object `null` values](xref:blazor/forms-validation#binding-inputselect-options-to-c-object-null-values)
* [ASP.NET Core Blazor event handling: `EventCallback` section](xref:blazor/components/event-handling#eventcallback)
6 changes: 3 additions & 3 deletions aspnetcore/blazor/components/event-handling.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,9 @@ Custom events with custom event arguments are generally enabled with the followi

```html
<script>
Blazor.registerCustomEventType('customevent', {
createEventArgs: eventArgsCreator;
});
Blazor.registerCustomEventType('customevent', {
createEventArgs: eventArgsCreator;
});
</script>
```

Expand Down
101 changes: 77 additions & 24 deletions aspnetcore/blazor/forms-validation.md
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,83 @@ In the following example:
> [!NOTE]
> Changing the <xref:Microsoft.AspNetCore.Components.Forms.EditContext> after its assigned is **not** supported.

::: moniker range=">= aspnetcore-6.0"

## Multiple option selection with the `InputSelect` component

*This feature applies to ASP.NET Core 6.0 Preview 7 or later. ASP.NET Core 6.0 is scheduled for release later this year.*

Binding supports [`multiple`](https://developer.mozilla.org/docs/Web/HTML/Attributes/multiple) option selection with the <xref:Microsoft.AspNetCore.Components.Forms.InputSelect%601> component. The [`@onchange`](xref:mvc/views/razor#onevent) event provides an array of the selected options via [event arguments (`ChangeEventArgs`)](xref:blazor/components/event-handling#event-arguments). The value must be bound to an array type, and binding to an array type makes the [`multiple`](https://developer.mozilla.org/docs/Web/HTML/Attributes/multiple) attribute optional on the <xref:Microsoft.AspNetCore.Components.Forms.InputSelect%601> tag.

In the following example, the user must select at least two starship classifications but no more than three classifications.

`Pages/BindMultipleWithInputSelect.razor`:

```razor
@page "/bind-multiple-with-inputselect"
@using System.ComponentModel.DataAnnotations
@using Microsoft.Extensions.Logging
@inject ILogger<BindMultipleWithInputSelect> Logger

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

<EditForm EditContext="@editContext" OnValidSubmit="@HandleValidSubmit">
<DataAnnotationsValidator />
<ValidationSummary />

<p>
<label>
Select one or more classifications (Minimum: 2, Maximum: 3):
<InputSelect @bind-Value="starship.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>
</p>

<button type="submit">Submit</button>
</EditForm>

<p>
Selected Classifications:
@string.Join(", ", starship.SelectedClassification)
</p>

@code {
private EditContext editContext;
private Starship starship = new();

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

private void HandleValidSubmit()
{
Logger.LogInformation("HandleValidSubmit called");
}

private class Starship
{
[Required, MinLength(2), MaxLength(3)]
public Classification[] SelectedClassification { get; set; } =
new[] { Classification.Diplomacy };
}

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

For information on how empty strings and `null` values are handled in data binding, see the [Binding `InputSelect` options to C# object `null` values](#binding-inputselect-options-to-c-object-null-values) section.

::: moniker-end

## Binding `InputSelect` options to C# object `null` values

For information on how empty strings and `null` values are handled in data binding, see <xref:blazor/components/data-binding#binding-select-element-options-to-c-object-null-values>.

::: moniker range=">= aspnetcore-5.0"

## Display name support
Expand Down Expand Up @@ -1110,30 +1187,6 @@ The following `RadioButtonExample` component uses the preceding `InputRadio` com

::: moniker-end

## Binding `<select>` element options to C# object `null` values

There's no sensible way to represent a `<select>` element option value as a C# object `null` value, because:

* HTML attributes can't have `null` values. The closest equivalent to `null` in HTML is absence of the HTML `value` attribute from the `<option>` element.
* When selecting an `<option>` with no `value` attribute, the browser treats the value as the *text content* of that `<option>`'s element.

The Blazor framework doesn't attempt to suppress the default behavior because it would involve:

* Creating a chain of special-case workarounds in the framework.
* Breaking changes to current framework behavior.

::: moniker range=">= aspnetcore-5.0"

The most plausible `null` equivalent in HTML is an *empty string* `value`. The Blazor framework handles `null` to empty string conversions for two-way binding to a `<select>`'s value.

::: moniker-end

::: moniker range="< aspnetcore-5.0"

The Blazor framework doesn't automatically handle `null` to empty string conversions when attempting two-way binding to a `<select>`'s value. For more information, see [Fix binding `<select>` to a null value (dotnet/aspnetcore #23221)](https://github.com/dotnet/aspnetcore/pull/23221).

::: moniker-end

## Validation Summary and Validation Message components

The <xref:Microsoft.AspNetCore.Components.Forms.ValidationSummary> component summarizes all validation messages, which is similar to the [Validation Summary Tag Helper](xref:mvc/views/working-with-forms#the-validation-summary-tag-helper):
Expand Down