Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[HxMultiSelect] Adds Floating Label type to MultiSelect component #899

Merged
24 changes: 23 additions & 1 deletion Havit.Blazor.Components.Web.Bootstrap/Forms/HxMultiSelect.cs
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ namespace Havit.Blazor.Components.Web.Bootstrap;
/// </summary>
/// <typeparam name="TValue">Type of values.</typeparam>
/// <typeparam name="TItem">Type of items.</typeparam>
public class HxMultiSelect<TValue, TItem> : HxInputBase<List<TValue>>, IInputWithSize
public class HxMultiSelect<TValue, TItem> : HxInputBase<List<TValue>>, IInputWithSize, IInputWithLabelType
{
/// <summary>
/// Return <see cref="HxMultiSelect{TValue, TItem}"/> defaults.
@@ -161,6 +161,26 @@ public class HxMultiSelect<TValue, TItem> : HxInputBase<List<TValue>>, IInputWit
[Parameter] public IconBase FilterClearIcon { get; set; }
protected IconBase FilterClearIconEffective => FilterClearIcon ?? GetSettings()?.FilterClearIcon ?? GetDefaults().FilterClearIcon;

/// <inheritdoc cref="Bootstrap.LabelType" />
[Parameter] public LabelType? LabelType { get; set; }
protected LabelType LabelTypeEffective => LabelType ?? GetSettings()?.LabelType ?? GetDefaults()?.LabelType ?? HxSetup.Defaults.LabelType;
LabelType IInputWithLabelType.LabelTypeEffective => LabelTypeEffective;
protected override LabelValueRenderOrder RenderOrder
{
get
{
if (LabelTypeEffective == Bootstrap.LabelType.Floating)
{
// Floating label type renders the label in HxMultiSelectInternal component.
return LabelValueRenderOrder.ValueOnly;
}
else
{
return LabelValueRenderOrder.LabelValue;
}
}
}

private List<TItem> _itemsToRender;
private HxMultiSelectInternal<TValue, TItem> _hxMultiSelectInternalComponent;

@@ -212,6 +232,8 @@ protected override void BuildRenderInput(RenderTreeBuilder builder)
builder.AddAttribute(102, nameof(HxMultiSelectInternal<TValue, TItem>.InputCssClass), GetInputCssClassToRender());
builder.AddAttribute(103, nameof(HxMultiSelectInternal<TValue, TItem>.InputText), GetInputText());
builder.AddAttribute(104, nameof(HxMultiSelectInternal<TValue, TItem>.EnabledEffective), EnabledEffective);
builder.AddAttribute(125, nameof(HxMultiSelectInternal<TValue, TItem>.LabelTypeEffective), LabelTypeEffective);
builder.AddAttribute(126, nameof(HxMultiSelectInternal<TValue, TItem>.FormValueComponent), this);
builder.AddAttribute(105, nameof(HxMultiSelectInternal<TValue, TItem>.ItemsToRender), _itemsToRender);
builder.AddAttribute(106, nameof(HxMultiSelectInternal<TValue, TItem>.TextSelector), TextSelector);
builder.AddAttribute(107, nameof(HxMultiSelectInternal<TValue, TItem>.ValueSelector), ValueSelector);
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@
bool enabled = EnabledEffective && (ItemsToRender != null);
}
<div class="@CssClassHelper.Combine("hx-multi-select",
HasInputGroups ? "input-group" : null,
HasInputGroups ? "input-group" : null,
HasInputGroupEnd ? "input-group-end" : null,
HasInputGroupStart ? "input-group-start" : null,
InputGroupCssClass)">
@@ -16,19 +16,26 @@
}

@InputGroupStartTemplate
<div @ref="_elementReference" class="dropdown" role="listbox">
<div @ref="_elementReference"
class="@CssClassHelper.Combine("dropdown", (LabelTypeEffective == LabelType.Floating) ? "form-floating": null)"
role="listbox">

<input @ref="_inputElementReference"
type="text"
id="@InputId"
class="@InputCssClass"
value="@(((ItemsToRender == null) && !String.IsNullOrEmpty(NullDataText)) ? NullDataText : InputText)"
disabled="@(!enabled)"
readonly="true"
aria-expanded="@_isShown"
data-bs-toggle="@(enabled ? "dropdown" : null)"
data-bs-auto-close="outside"
@attributes="this.AdditionalAttributes" />
type="text"
id="@InputId"
class="@InputCssClass"
value="@(((ItemsToRender == null) && !String.IsNullOrEmpty(NullDataText)) ? NullDataText : InputText)"
disabled="@(!enabled)"
readonly="true"
aria-expanded="@_isShown"
data-bs-toggle="@(enabled ? "dropdown" : null)"
data-bs-auto-close="outside"
@attributes="this.AdditionalAttributes" />

@if (LabelTypeEffective == LabelType.Floating)
{
<HxFormValueComponentRenderer_Label FormValueComponent="@FormValueComponent" />
}

@* Must be always rendered otherwise does not work after disable->enabled scenario *@
<ul class="@CssClassHelper.Combine("dropdown-menu", _isShown ? "show" : null)">
@@ -45,7 +52,7 @@
autocomplete="off"
value="@_filterText"
@oninput="HandleFilterInputChanged"
@onclick:stopPropagation
@onclick:stopPropagation
onfocusin="this.select()" />

<div class="hx-multi-select-filter-input-icon">
Original file line number Diff line number Diff line change
@@ -13,8 +13,12 @@ public partial class HxMultiSelectInternal<TValue, TItem> : IAsyncDisposable

[Parameter] public string InputText { get; set; }

[Parameter] public IFormValueComponent FormValueComponent { get; set; }

[Parameter] public bool EnabledEffective { get; set; }

[Parameter] public LabelType LabelTypeEffective { get; set; }

[Parameter] public List<TItem> ItemsToRender { get; set; }

[Parameter] public List<TValue> SelectedValues { get; set; }
Original file line number Diff line number Diff line change
@@ -12,6 +12,11 @@ public record MultiSelectSettings : InputSettings
/// </summary>
public InputSize? InputSize { get; set; }

/// <summary>
/// The label type.
/// </summary>
public LabelType? LabelType { get; set; }

/// <summary>
/// Enables filtering capabilities.
/// </summary>
Original file line number Diff line number Diff line change
@@ -4699,6 +4699,9 @@
Icon displayed in filter input for clearing the filter.
</summary>
</member>
<member name="P:Havit.Blazor.Components.Web.Bootstrap.HxMultiSelect`2.LabelType">
<inheritdoc cref="T:Havit.Blazor.Components.Web.Bootstrap.LabelType" />
</member>
<member name="M:Havit.Blazor.Components.Web.Bootstrap.HxMultiSelect`2.FocusAsync">
<inheritdoc cref="M:Havit.Blazor.Components.Web.Bootstrap.HxInputBase`1.FocusAsync"/>
</member>
@@ -5429,6 +5432,11 @@
Input size.
</summary>
</member>
<member name="P:Havit.Blazor.Components.Web.Bootstrap.MultiSelectSettings.LabelType">
<summary>
The label type.
</summary>
</member>
<member name="P:Havit.Blazor.Components.Web.Bootstrap.MultiSelectSettings.AllowFiltering">
<summary>
Enables filtering capabilities.
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
@page "/HxMultiSelect_FloatingLabel"
@rendermode InteractiveServer
@inject IDemoDataService DemoDataService

<div class="m-3">

<HxMultiSelect Label="HxMultiSelect"
TItem="EmployeeDto"
TValue="int"
Data="@employees"
LabelType="LabelType.Floating"
@bind-Value="selectedEmployeeIds"
TextSelector="@(p => p.Name)"
ValueSelector="@(p => p.Id)"
NullDataText="Loading employees..."
EmptyText="-select employees-" />

For visual reference:
<HxSelect TItem="EmployeeDto"
TValue="int?"
Label="HxSelect"
LabelType="LabelType.Floating"
Data="employees"
@bind-Value="selectedEmployeeId"
TextSelector="@(employee => employee.Name)"
ValueSelector="@(employee => employee.Id)"
Nullable="true"
NullText="-select employee-"
NullDataText="Loading employees..." />

</div>


<p class="mt-3">Selected employees (IDs): @String.Join(", ", selectedEmployeeIds.Select(e => e.ToString()))</p>

@code {
private IEnumerable<EmployeeDto> employees;
private List<int> selectedEmployeeIds = new();
private int? selectedEmployeeId;

protected override async Task OnInitializedAsync()
{
employees = await DemoDataService.GetAllEmployeesAsync();
}
}