P11SelectMultiple Component
P11SelectMultiple component provides a multi-selection dropdown list, wrapping the native HTML <select multiple> element. It enables users to select multiple options from a predefined list, integrated with Bootstrap's .form-select class for consistent styling and offering flexible data binding and accessibility features.P11Select, options can be populated via an Items collection with expressions/fields, or manually through ChildContent. Ensure your binding target (@bind-Value) for this component is an ICollection<TValue> (e.g., List<string> or HashSet<int>) to correctly handle multiple selections.P11SelectMultiple Component Examples
These examples demonstrate various configurations and functionalities of the P11SelectMultiple component, showcasing its flexibility for different use cases.
1. Standard Usage with List of Objects (Multiple Selection)
Selecting multiple names from a list of <code>Person</code> objects.
Selected Person IDs: Nothing selected
Implementation
<label for="multiPersonSelect" class="form-label">Wähle Personen (Mehrfachauswahl):</label>
<P11SelectMultiple TItem="Person" TValue="int"
Id="multiPersonSelect"
@bind-Value="selectedPersonIds"
Items="people2"
ItemValueExpression="p => p.Id"
ItemTextExpression="p => p.Name"
PlaceholderText="-- Keine Auswahl --"
OnChanged="@OnMultiplePersonsChanged"
CssClass="form-select-lg"
AriaLabel="Mehrere Personen auswählen Dropdown">
</P11SelectMultiple>
<p class="mt-2">
Ausgewählte Personen IDs:
<strong>
@(selectedPersonIds != null && selectedPersonIds.Any()
? string.Join(", ", selectedPersonIds)
: "Nichts ausgewählt")
</strong>
</p>
@if (!string.IsNullOrEmpty(multiPersonChangedMessage))
{
<p class="text-info">@multiPersonChangedMessage</p>
}
private ICollection<int> selectedPersonIds = new List<int>(); // List<int> for multiple selection
private string? multiPersonChangedMessage;
private List<Person> people2 = new List<Person>
{
new Person { Id = 1, Name = "Alice", City = "New York" },
new Person { Id = 2, Name = "Bob", City = "London" },
new Person { Id = 3, Name = "Charlie", City = "Paris" },
new Person { Id = 4, Name = "Diana", City = "Berlin" }
};
private void OnMultiplePersonsChanged(ICollection<int> newPersonIds)
{
multiPersonChangedMessage = $"Personen geändert zu: {string.Join(", ", newPersonIds ?? new List<int>())}";
Console.WriteLine(multiPersonChangedMessage);
}
public class Person
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public string City { get; set; } = string.Empty;
}
2. Usage with Enum (Multiple Selection)
Selecting multiple priorities from an <code>enum</code>.
Selected Priorities: Nothing selected
Implementation
<label for="multiPrioritySelect" class="form-label">Wähle Prioritäten (Mehrfachauswahl):</label>
<P11SelectMultiple TItem="Priority" TValue="Priority"
Id="multiPrioritySelect"
@bind-Value="selectedPriorities"
Items="@Enum.GetValues<Priority>()"
ItemValueExpression="p => p"
ItemTextExpression="p => p.ToString()"
PlaceholderText="-- Wähle Prioritäten --"
AriaLabel="Mehrere Prioritäten auswählen Dropdown">
</P11SelectMultiple>
<p class="mt-2">
Ausgewählte Prioritäten:
<strong>
@(selectedPriorities != null && selectedPriorities.Any()
? string.Join(", ", selectedPriorities)
: "Nichts ausgewählt")
</strong>
</p>
private ICollection<Priority> selectedPriorities = new List<Priority>(); // List<Priority> for multiple enum selection
public enum Priority
{
Low,
Medium,
High,
Critical
}
3. Manual Options (ChildContent) (Multiple Selection)
Direct rendering of <code><option></code> tags within the component for multiple selection.
Selected Cities: MUN
Implementation
<label for="multiCitySelect" class="form-label">Wähle Städte manuell (Mehrfachauswahl):</label>
<P11SelectMultiple TItem="string" TValue="string"
Id="multiCitySelect"
@bind-Value="selectedCities"
PlaceholderText="Wähle Städte manuell"
AriaLabel="Mehrere Städte auswählen Dropdown">
<option value="BER">Berlin</option>
<option value="MUN">München</option>
<option value="HAM">Hamburg</option>
<option value="COL">Köln</option>
<option value="FRA">Frankfurt</option>
</P11SelectMultiple>
<p class="mt-2">
Ausgewählte Städte:
<strong>
@(selectedCities != null && selectedCities.Any()
? string.Join(", ", selectedCities)
: "Nichts ausgewählt")
</strong>
</p>
private ICollection<string> selectedCities = new List<string> { "MUN" }; // Pre-selected for manual example
4. Disabled Select (Multiple Selection)
A multi-selection field that is not interactive.
Disabled Selection: 1, 3
Implementation
<label for="disabledMultiSelect" class="form-label">Deaktivierte Mehrfachauswahl:</label>
<P11SelectMultiple TItem="Person" TValue="int"
Id="disabledMultiSelect"
@bind-Value="disabledSelectedPersonIds"
Items="people2"
ItemValueExpression="p => p.Id"
ItemTextExpression="p => p.Name"
IsDisabled="true"
PlaceholderText="Auswahl deaktiviert"
AriaLabel="Deaktiviertes Mehrfachauswahl Dropdown">
</P11SelectMultiple>
<p class="mt-2">
Deaktivierte Auswahl:
<strong>
@(disabledSelectedPersonIds != null && disabledSelectedPersonIds.Any()
? string.Join(", ", disabledSelectedPersonIds)
: "Nichts ausgewählt")
</strong>
</p>
private ICollection<int> disabledSelectedPersonIds = new List<int> { 1, 3 }; // Pre-selected for disabled example
5. Validation in EditForm (Multiple Selection)
Demonstrates integration with Blazor's <code>EditForm</code> and validation mechanisms for multiple selection.
Implementation
<EditForm Model="validationModelMultiple" OnValidSubmit="HandleValidSubmit3" OnInvalidSubmit="HandleInvalidSubmit3">
<DataAnnotationsValidator />
<ValidationSummary />
<div class="mb-3">
<label for="requiredMultiPersonSelect" class="form-label">Pflichtfeld Personen (Mehrfachauswahl):</label>
<P11SelectMultiple TItem="Person" TValue="int"
Id="requiredMultiPersonSelect"
@bind-Value="validationModelMultiple.SelectedRequiredPersonIds"
Items="people2"
ItemValueExpression="p => p.Id"
ItemTextExpression="p => p.Name"
PlaceholderText="-- Bitte wählen --"
AriaLabel="Pflichtfeld Personen Dropdown">
</P11SelectMultiple>
<ValidationMessage For="@(() => validationModelMultiple.SelectedRequiredPersonIds)" />
</div>
<div class="mb-3">
<label for="requiredMultiPrioritySelect" class="form-label">Pflichtfeld Prioritäten (Mehrfachauswahl):</label>
<P11SelectMultiple TItem="Priority" TValue="Priority"
Id="requiredMultiPrioritySelect"
@bind-Value="validationModelMultiple.SelectedRequiredPriorities"
Items="@Enum.GetValues<Priority>()"
ItemValueExpression="p => p"
ItemTextExpression="p => p.ToString()"
PlaceholderText="-- Bitte wählen --"
AriaLabel="Pflichtfeld Prioritäten Dropdown">
</P11SelectMultiple>
<ValidationMessage For="@(() => validationModelMultiple.SelectedRequiredPriorities)" />
</div>
<button type="submit" class="btn btn-primary">Formular absenden</button>
<p class="mt-2">Validierungsstatus: <strong>@validationStatus3</strong></p>
</EditForm>
private ValidationTestModelMultiple validationModelMultiple = new ValidationTestModelMultiple();
private string validationStatus3 = "Warten auf Absenden...";
private void HandleValidSubmit3()
{
validationStatus3 = "Formular ist GÜLTIG!";
Console.WriteLine($"Validierung erfolgreich. Personen: {string.Join(", ", validationModelMultiple.SelectedRequiredPersonIds ?? new List<int>())}, Prioritäten: {string.Join(", ", validationModelMultiple.SelectedRequiredPriorities ?? new List<Priority>())}");
}
private void HandleInvalidSubmit3()
{
validationStatus3 = "Formular ist UNGÜLTIG!";
Console.WriteLine("Validierung fehlgeschlagen.");
}
public class ValidationTestModelMultiple
{
[Required(ErrorMessage = "Bitte wählen Sie mindestens eine Person aus.")]
// For collections, Required checks if the collection is null.
// To check if it's empty, you might need a custom validation attribute or check in OnValidSubmit.
// However, a simple Required will catch a null collection.
public ICollection<int>? SelectedRequiredPersonIds { get; set; } = new List<int>();
[Required(ErrorMessage = "Bitte wählen Sie mindestens eine Priorität aus.")]
public ICollection<Priority>? SelectedRequiredPriorities { get; set; } = new List<Priority>();
}
6. OnChanged Event Example
This example demonstrates how to use the <code>OnChanged</code> event to react to changes in the selected values. The current selections are displayed immediately after a change.
Selected Languages (via OnChanged): None
Implementation
<label for="programmingLanguageSelect" class="form-label">Wähle Programmiersprachen:</label>
<P11SelectMultiple TItem="string" TValue="string"
Id="programmingLanguageSelect"
@bind-Value="selectedProgrammingLanguages"
OnChanged="@OnProgrammingLanguagesChanged"
Items="programmingLanguageOptions"
ItemValueExpression="lang => lang"
ItemTextExpression="lang => lang"
PlaceholderText="-- Wähle Sprachen --"
AriaLabel="Programmiersprachen auswählen Dropdown">
</P11SelectMultiple>
<p class="mt-2">
Ausgewählte Sprachen (via OnChanged):
<strong>
@(selectedProgrammingLanguages != null && selectedProgrammingLanguages.Any()
? string.Join(", ", selectedProgrammingLanguages)
: "None")
</strong>
</p>
@if (!string.IsNullOrEmpty(programmingLanguagesChangedMessage))
{
<p class="text-info">@programmingLanguagesChangedMessage</p>
}
private ICollection<string> selectedProgrammingLanguages = new List<string>();
private string? programmingLanguagesChangedMessage;
private List<string> programmingLanguageOptions = new() { "C#", "JavaScript", "Python", "Java", "TypeScript", "Go" };
private void OnProgrammingLanguagesChanged(ICollection<string> newValues)
{
// selectedProgrammingLanguages wird bereits durch @bind-Value aktualisiert.
// Wir nutzen newValues hier, um die Event-Payload zu demonstrieren.
programmingLanguagesChangedMessage = $"Sprachen geändert zu: {string.Join(", ", newValues ?? new List<string>())} um {DateTime.Now:HH:mm:ss}";
Console.WriteLine($"Programming languages changed to: {string.Join(", ", newValues ?? new List<string>())}");
}
Component API
| Parameter | Type | Default | Description |
|---|---|---|---|
Items |
IEnumerable<TItem>? |
null |
Gets or sets the collection of items to display in the select dropdown. |
ItemValueExpression |
Expression<Func<TItem, TValue>>? |
null |
Gets or sets an expression that specifies which property of TItem should be used as the value for each option. This is the preferred way over ItemValueField for type safety and AOT/trimming compatibility. |
ItemTextExpression |
Expression<Func<TItem, string>>? |
null |
Gets or sets an expression that specifies which property of TItem should be used as the display text for each option. This is the preferred way over ItemTextField for type safety and AOT/trimming compatibility. |
ItemValueField |
string? |
null |
Gets or sets the name of the property in TItem to use as the value for each option. Use ItemValueExpression for better type safety and AOT/trimming compatibility. |
ItemTextField |
string? |
null |
Gets or sets the name of the property in TItem to use as the display text for each option. Use ItemTextExpression for better type safety and AOT/trimming compatibility. |
Id |
string? |
null |
Gets or sets the HTML 'id' attribute for the select element. Recommended for accessibility, especially when used with a <label>. |
Name |
string? |
null |
Gets or sets the HTML 'name' attribute for the select element. |
CssClass |
string? |
null |
Gets or sets additional CSS classes to apply to the select element. |
IsDisabled |
bool |
false |
Gets or sets a value indicating whether the select element should be disabled. |
AriaLabel |
string? |
null |
Gets or sets the ARIA label for accessibility. Provides a descriptive label for screen readers. Important if no visual label is associated via 'id' or 'for'. |
Title |
string? |
null |
Gets or sets the HTML 'title' attribute for the select element. Provides a tooltip on hover and can act as a fallback accessible name. |
PlaceholderText |
string? |
null |
Gets or sets the text for a default placeholder option. |
PlaceholderValue |
string |
string.Empty |
Gets or sets the value for the default placeholder option. |
PlaceholderIsDisabled |
bool |
true |
Gets or sets a value indicating whether the placeholder option should be disabled (not selectable). |
NoOptionsText |
string |
\"No options available\" |
Gets or sets the text to display when no options are available (and no placeholder or ChildContent is provided). |
ChildContent |
RenderFragment? |
null |
Gets or sets the content to render inside the <select> element, typically used to define custom <option> elements manually. |
SkipValidation |
bool |
false |
Gets or sets a value indicating whether to skip the internal configuration validation checks. |
| Events | |||
OnChanged |
EventCallback<ICollection<TValue>> |
- | An EventCallback that is invoked when the selected values of the component change. The callback receives the new collection of values as its argument. This complements the @bind-Value parameter. |