Skip to main content

LgSelect

LgSelect<TValue> is the single-selection dropdown list. Options are declared in markup within <Items> (with LgOptionListItem), or come from a data source (DataSourceItems / DataSource); an integrated search area can filter the options.

<LgSelect Label="#Color" Placeholder="#ChooseColor" @bind-Value="_model.Color">
<Items>
<LgOptionListItem Text="#Blue" Value="@("blue")" />
<LgOptionListItem Text="#Green" Value="@("green")" />
</Items>
</LgSelect>
  • Namespace : Lagoon.UI.Components
  • Inherits from : LgSelectBase<TValue, TValue> → LgInputRenderBase<TValue> → LgInputBase<TValue> → LgAriaComponentBase → LgComponentBase
  • NuGet package : Lagoon.UI
Multiple selection and assisted input

To bind a collection of values, use LgSelectMultiple (API Reference). For free input with suggestions, use LgSuggestBox.

Usage​

Demo​

Try this component in the Lagoon showcase.

Options in markup​

Each option is an LgOptionListItem carrying its text and value.

ColorSelectPage.razor
<LgSelect Label="#Color" Placeholder="#ChooseColor" @bind-Value="_model.Color">
<Items>
@foreach (ColorItem item in _colors)
{
<LgOptionListItem Text="@item.Label" Value="@item.Value" />
}
</Items>
</LgSelect>
ColorSelectPage.razor.cs
public partial class ColorSelectPage : LgPage
{
// Options displayed: the label / value pair feeds the LgOptionListItem.
private readonly List<ColorItem> _colors = new()
{
new ColorItem("Blue", "blue"),
new ColorItem("Green", "green"),
new ColorItem("Red", "red")
};

private readonly ColorVm _model = new();

private sealed record ColorItem(string Label, string Value);

private sealed class ColorVm
{
public string Color { get; set; }
}
}

Populating from a data source​

DataSourceItems feeds the list from a collection; DataSource (IListDataSource) handles advanced scenarios (separate text / value, on-demand loading) — see the API Reference for expected types.

CountrySelectPage.razor
<LgSelect Label="#Country"
DataSourceItems="_countries"
@bind-Value="_model.Country" />
CountrySelectPage.razor.cs
public partial class CountrySelectPage : LgPage
{
// Direct data source: each element is both the text and the value.
private readonly List<string> _countries = new() { "France", "Germany", "Spain", "Italy" };

private readonly CountryVm _model = new();

private sealed class CountryVm
{
public string Country { get; set; }
}
}

Remote data source and cascading select lists​

RemoteListDataSource<TItem, TValue> loads options from a [Queryable] controller action (see Queryable attribute): TItem is the type returned by the server (a view model), TValue is the type of the bound value, and the two selectors extract the value and text from each element. ControllerQueryArg passes a business argument to the controller, received in a QueryArg<T>.

For a select that depends on another (the firms in the chosen country), simply modify the ControllerQueryArg of the source: the select reloads its list with the new argument.

FirmSelectPage.razor
<LgSelect Label="#Country"
DataSource="_countriesDataSource"
OnChange="OnCountryChanged"
@bind-Value="_model.CountryId" />
<LgSelect Label="#Firm"
DataSource="_firmsDataSource"
@bind-Value="_model.FirmId" />
FirmSelectPage.razor.cs
public partial class FirmSelectPage : LgPage
{
private readonly FirmVm _model = new();

private RemoteListDataSource<VmCountry, int?> _countriesDataSource;

private RemoteListDataSource<VmCountryFirm, Guid?> _firmsDataSource;

protected override void OnInitialized()
{
base.OnInitialized();
_countriesDataSource = new RemoteListDataSource<VmCountry, int?>(
"api/Countries/names", x => x.Id, x => x.Name);
// Argument received by the GetFirmsByCountry action in a QueryArg<int?>.
_firmsDataSource = new RemoteListDataSource<VmCountryFirm, Guid?>(
"api/Firms/GetFirmsByCountry", x => x.Id, x => x.FirmName)
{
ControllerQueryArg = _model.CountryId
};
}

private Task OnCountryChanged()
{
// The selected firm belongs to the previous country: clear it.
_model.FirmId = null;
// Changing the argument is sufficient to reload the list of firms.
_firmsDataSource.ControllerQueryArg = _model.CountryId;
return Task.CompletedTask;
}

private sealed class FirmVm
{
public int? CountryId { get; set; }

public Guid? FirmId { get; set; }
}
}

When ControllerQueryArg changes (assigning the same value is ignored), the select abandons its list and requests a new one from the server:

  • immediately if the list is open, if a load is in progress (it is canceled then relaunched with the new argument: the outdated response is never displayed) or if there remains a label of a selected value to resolve;
  • otherwise on the next open of the list, without unnecessary request.
warning
Selected value and ResetDataSource()
  • The selected value is not cleared when the argument changes: if it no longer belongs to the new list, reset it to null in the handler that changes the argument (as in OnCountryChanged above).
  • Do not call ResetDataSource() before or after modifying ControllerQueryArg: changing the argument already reloads the select. Called just before, ResetDataSource() may send a request with the old argument, immediately canceled. Reserve ResetDataSource() for reloading without argument change (data modified on the server side, for example).

The same behavior applies to LgSelectMultiple.

Searching in options​

ShowSearchBox displays the search area, MinSearchCharacter sets the number of characters before filtering, and OnFilterChange notifies each search (useful for reloading a source on demand).

CitySelectPage.razor
<LgSelect Label="#City"
ShowSearchBox="true"
MinSearchCharacter="2"
OnFilterChange="OnFilterChangeAsync"
DataSourceItems="_cities"
@bind-Value="_model.City" />
CitySelectPage.razor.cs
public partial class CitySelectPage : LgPage
{
private List<string> _cities = new() { "Paris", "Lyon", "Marseille" };

private readonly CityVm _model = new();

// Triggered on each search: entry point for reloading the source on demand.
private async Task OnFilterChangeAsync(FilterChangeEventArgs args)
{
await Task.Delay(100);
ShowInformation("#SearchDone");
}

private sealed class CityVm
{
public string City { get; set; }
}
}

Canceling a selection change​

OnChangingAsync is called before assignment and allows canceling the change (args.Cancel); OnChange (inherited) is called after.

StatusSelectPage.razor
<LgSelect Label="#Status"
OnChangingAsync="OnStatusChangingAsync"
@bind-Value="_model.Status">
<Items>
<LgOptionListItem Text="#Draft" Value="@("draft")" />
<LgOptionListItem Text="#Published" Value="@("published")" />
<LgOptionListItem Text="#Archived" Value="@("archived")" />
</Items>
</LgSelect>
StatusSelectPage.razor.cs
public partial class StatusSelectPage : LgPage
{
private readonly StatusVm _model = new();

// Called before the change: prevents archiving directly from draft.
private Task OnStatusChangingAsync(ChangingEventArgs<string> args)
{
if (args.OldValue == "draft" && args.NewValue == "archived")
{
args.Cancel = true;
ShowWarning("#PublishBeforeArchive");
}
return Task.CompletedTask;
}

private sealed class StatusVm
{
public string Status { get; set; } = "draft";
}
}

Properties​

All [Parameter] properties of the component, including inherited ones.

NameTypeDefaultDeclared inDescription
OnChangingAsyncFunc<ChangingEventArgs<TValue>, Task>nullLgSelectCallback called before the value changes; the change can be canceled here.
DataSourceIListDataSource<TValue>nullLgSelectBaseData source for the list (separate text / value, on-demand loading).
DataSourceItemsIEnumerable<TValue>nullLgSelectBaseList items provided directly.
DropDownMaxHeightint0LgSelectBaseMaximum height of the dropdown list, in pixels. If 0 or less, the application configuration applies.
InputMaskstringnullLgSelectBaseInput mask applied to the search area.
InputMaskKindInputMaskKindNoneLgSelectBaseType of input mask for the search area.
InputMaskPlaceholderstringnullLgSelectBaseCharacter filling empty mask positions (for example # with the mask 99-99-99-99-99 displays ##-##-##-##-##). Not to be confused with Placeholder. Without a value, the mask's default character (_) is kept. Applies to the search area of the dropdown menu.
ItemsRenderFragmentnullLgSelectBaseOptions declared in markup (LgOptionListItem).
MinSearchCharacterint0LgSelectBaseMinimum number of characters before filtering (and before OnFilterChange in on-demand loading).
OnFilterChangeEventCallback<FilterChangeEventArgs>—LgSelectBaseCallback triggered when the user performs a search.
PlaceholderstringnullLgSelectBaseText displayed when no value is selected. Distinct from InputMaskPlaceholder.
SearchBoxCssClassstringnullLgSelectBaseAdditional CSS classes for the search area.
ShowSearchBoxbool?nullLgSelectBaseShows the search area. If null, the application configuration applies.
SuffixSearchBoxstringnullLgSelectBaseSuffix for the search area.
SuffixTypeSearchBoxInputLabelTypeIconNameLgSelectBaseNature of the search area suffix.
PrefixstringnullLgInputRenderBasePrefix displayed in the field.
PrefixTypeInputLabelTypeTextLgInputRenderBaseNature of the prefix.
SuffixstringnullLgInputRenderBaseSuffix displayed in the field.
SuffixTypeInputLabelTypeTextLgInputRenderBaseNature of the suffix.
AdditionalAttributesIReadOnlyDictionary<string, object>nullLgInputBaseAdditional HTML attributes applied to the rendered element.
AutoFocusboolfalseLgInputBaseGives focus to the field on first render.
ConfirmationMessagestringnullLgInputBaseConfirmation message displayed before applying a selection change.
ContainerIInputContainer<TValue>nullLgInputBaseInternal use: attaches a GridView cell to the field.
CssClassstringnullLgInputBaseAdditional CSS classes.
DisabledboolfalseLgInputBaseDisables the field.
DisplayNamestringnullLgInputBaseField name used in error messages.
HideValidationMessageboolfalseLgInputBaseHides the validation message below the field.
LabelstringnullLgInputBaseField label.
LabelContentRenderFragmentnullLgInputBaseCustom content for the label area.
OnChangeEventCallback<ChangeEventArgs>—LgInputBaseCallback called after the selection changes.
OnResetEventCallback<ChangeEventArgs>—LgInputBaseCallback called when the selection is cleared by the reset button.
PolicyEditstringnullLgInputBasePolicy required to edit the field.
PolicyVisiblestringnullLgInputBasePolicy required to display the field.
ReadOnlyboolfalseLgInputBaseDisplays the selection as read-only.
Requiredbool?nullLgInputBaseRequired field. If null, inferred from the [Required] attribute of the bound property. A required field does not display the reset button.
ResetButtonbool?nullLgInputBaseDisplays the selection reset button. If null, the application behavior configuration applies.
ResetTextstringnullLgInputBaseText of the reset button.
ResetTextAriaLabelstringnullLgInputBaseAccessible label (aria-label) of the reset button.
TooltipstringnullLgInputBaseHelp tooltip.
TooltipIsHtmlboolfalseLgInputBaseIndicates whether the Tooltip content is in HTML format (otherwise plain text).
ValueTValue—LgInputBaseSelected value (@bind-Value).
ValueChangedEventCallback<TValue>—LgInputBaseCallback for updating the bound value.
ValueExpressionExpression<Func<TValue>>—LgInputBaseExpression identifying the bound property.
AriaLabelstringnullLgAriaComponentBaseValue of the aria-label attribute.
AriaLabelledBystringnullLgAriaComponentBaseValue of the aria-labelledby attribute.
Cascading parameters

LgSelect also consumes parameters provided automatically by ancestor components (you do not need to define them): ParentAuthorizeView (LgAuthorizeView) and the edit context of a parent LgEditForm.

Events​

EventTypeDescription
OnChangingAsyncFunc<ChangingEventArgs<TValue>, Task>Before the selection changes; args.Cancel = true cancels it.
OnChangeEventCallback<ChangeEventArgs>After the selection changes.
OnFilterChangeEventCallback<FilterChangeEventArgs>When the user performs a search in the list.
OnResetEventCallback<ChangeEventArgs>When the selection is cleared by the reset button.

Associated enumerations​

The enumerations used are documented on the base components: InputMaskKind on LgTextBox and InputLabelType on LgDateBox.

Best practices / accessibility​

  • Enable ShowSearchBox whenever the list exceeds about ten options.
  • Use DataSource (rather than DataSourceItems) when the displayed text differs from the stored value or when the list loads on demand.
  • For few options always visible, prefer LgRadioGroup.
Complete reference

All parameters (including inherited ones): API Reference — LgSelect. For multiple selection, see LgSelectMultiple. For free input with suggestions, see LgSuggestBox.