add multiple select list
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
using GameIdeas.Shared.Dto;
|
using GameIdeas.Shared.Dto;
|
||||||
|
|
||||||
namespace GameIdeas.BlazorApp.Shared.Layouts.Header;
|
namespace GameIdeas.BlazorApp.Shared.Components.Account;
|
||||||
|
|
||||||
public class LoginValidator : AbstractValidator<LoginDto>
|
public class LoginValidator : AbstractValidator<LoginDto>
|
||||||
{
|
{
|
||||||
@@ -1,16 +1,27 @@
|
|||||||
<EditForm EditContext="EditContext">
|
<EditForm EditContext="EditContext">
|
||||||
<div class="search-container">
|
<div class="search-container">
|
||||||
<InputText class="search-field"
|
<InputText class="search-field"
|
||||||
@bind-Value=Text />
|
@bind-Value=Text />
|
||||||
|
|
||||||
|
@if (!string.IsNullOrEmpty(Text))
|
||||||
|
{
|
||||||
|
<div class="clear-icon" @onclick=HandleClearClicked>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
|
<path d="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
<div class="clear-icon" @onclick=HandleClearClicked>
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
|
||||||
<path d="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div type="submit" class="search-icon">
|
<div type="submit" class="search-icon">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
<path d="M9.5,3A6.5,6.5 0 0,1 16,9.5C16,11.11 15.41,12.59 14.44,13.73L14.71,14H15.5L20.5,19L19,20.5L14,15.5V14.71L13.73,14.44C12.59,15.41 11.11,16 9.5,16A6.5,6.5 0 0,1 3,9.5A6.5,6.5 0 0,1 9.5,3M9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5Z" />
|
@if (Icon == SearchInputIcon.Search)
|
||||||
|
{
|
||||||
|
<path d="M9.5,3A6.5,6.5 0 0,1 16,9.5C16,11.11 15.41,12.59 14.44,13.73L14.71,14H15.5L20.5,19L19,20.5L14,15.5V14.71L13.73,14.44C12.59,15.41 11.11,16 9.5,16A6.5,6.5 0 0,1 3,9.5A6.5,6.5 0 0,1 9.5,3M9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5Z" />
|
||||||
|
}
|
||||||
|
else if (Icon == SearchInputIcon.Dropdown)
|
||||||
|
{
|
||||||
|
<path style="fill: var(--violet)" d="M1 3H23L12 22" />
|
||||||
|
}
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ public partial class SearchInput
|
|||||||
{
|
{
|
||||||
[Parameter] public string? Text { get; set; }
|
[Parameter] public string? Text { get; set; }
|
||||||
[Parameter] public EventCallback<string> TextChanged { get; set; }
|
[Parameter] public EventCallback<string> TextChanged { get; set; }
|
||||||
|
[Parameter] public SearchInputIcon Icon { get; set; }
|
||||||
|
|
||||||
private EditContext? EditContext;
|
private EditContext? EditContext;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace GameIdeas.BlazorApp.Shared.Components.Search;
|
||||||
|
|
||||||
|
public enum SearchInputIcon
|
||||||
|
{
|
||||||
|
Search,
|
||||||
|
Dropdown
|
||||||
|
}
|
||||||
@@ -11,7 +11,6 @@ public partial class SelectListElement<TItem>
|
|||||||
{
|
{
|
||||||
if (Value != null)
|
if (Value != null)
|
||||||
{
|
{
|
||||||
Value.IsSelected = true;
|
|
||||||
await ValueChanged.InvokeAsync(Value);
|
await ValueChanged.InvokeAsync(Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,32 @@
|
|||||||
.select-element {
|
.select-element {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
|
width: 100%;
|
||||||
|
gap: 6px;
|
||||||
|
height: 20px;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.select-element:hover {
|
.select-element:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.selected {
|
||||||
|
width: 12px;
|
||||||
|
min-width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
min-height: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
.selected svg {
|
.selected svg {
|
||||||
|
display: block;
|
||||||
fill: var(--white)
|
fill: var(--white)
|
||||||
}
|
}
|
||||||
|
|
||||||
/***** Navigation Theme *****/
|
/***** Navigation Theme *****/
|
||||||
.navigation {
|
.navigation {
|
||||||
padding: 4px 8px;
|
padding: 4px 8px;
|
||||||
width: 100%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.navigation .selected {
|
.navigation .selected {
|
||||||
@@ -26,10 +39,6 @@
|
|||||||
|
|
||||||
/***** Sort Theme *****/
|
/***** Sort Theme *****/
|
||||||
.sort {
|
.sort {
|
||||||
gap: 6px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
width: 100%;
|
|
||||||
padding: 2px 6px;
|
padding: 2px 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,11 +46,6 @@
|
|||||||
background: var(--low-white);
|
background: var(--low-white);
|
||||||
}
|
}
|
||||||
|
|
||||||
.sort .selected {
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sort .select-label {
|
.sort .select-label {
|
||||||
text-wrap: nowrap;
|
text-wrap: nowrap;
|
||||||
margin-right: 6px;
|
margin-right: 6px;
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
@using GameIdeas.BlazorApp.Shared.Components.Search
|
||||||
|
@using GameIdeas.BlazorApp.Shared.Components.Select.Components
|
||||||
|
@typeparam TItem
|
||||||
|
|
||||||
|
<div class="select-list" @onclick=HandleButtonClicked>
|
||||||
|
<div class="select-button">
|
||||||
|
<SearchInput Icon="SearchInputIcon.Dropdown"
|
||||||
|
Text="Text"
|
||||||
|
TextChanged="HandleTextChanged"/>
|
||||||
|
</div>
|
||||||
|
<div @ref=Container @onfocusout=HandleFocusOut
|
||||||
|
class="select-container @(AlignRight ? "align-right" : "")"
|
||||||
|
tabindex="1000">
|
||||||
|
|
||||||
|
@if (ContentVisile)
|
||||||
|
{
|
||||||
|
<div class="select-content @(Enum.GetName(Theme)?.ToLower())">
|
||||||
|
@foreach (var item in Items)
|
||||||
|
{
|
||||||
|
<SelectListElement TItem="TItem"
|
||||||
|
Value="item"
|
||||||
|
ValueChanged="HandleItemClicked"
|
||||||
|
Theme="Theme" />
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
|
||||||
|
namespace GameIdeas.BlazorApp.Shared.Components.Select;
|
||||||
|
|
||||||
|
public partial class MultipleSelectList<TItem>
|
||||||
|
{
|
||||||
|
[Parameter] public IEnumerable<TItem>? Values { get; set; }
|
||||||
|
[Parameter] public EventCallback<IEnumerable<TItem>?> ValuesChanged { get; set; }
|
||||||
|
[Parameter] public IEnumerable<SelectElement<TItem>> Items { get; set; } = [];
|
||||||
|
[Parameter] public SelectListTheme Theme { get; set; }
|
||||||
|
[Parameter] public bool AlignRight { get; set; }
|
||||||
|
|
||||||
|
private bool ContentVisile = false;
|
||||||
|
private DateTime ContentLastFocusOut = DateTime.Now;
|
||||||
|
private ElementReference Container;
|
||||||
|
private string? Text;
|
||||||
|
|
||||||
|
public async Task OpenAsync()
|
||||||
|
{
|
||||||
|
if (DateTime.Now - ContentLastFocusOut >= TimeSpan.FromSeconds(0.2))
|
||||||
|
{
|
||||||
|
await Container.FocusAsync();
|
||||||
|
ContentVisile = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close() => ContentVisile = false;
|
||||||
|
|
||||||
|
private async Task HandleButtonClicked() => await OpenAsync();
|
||||||
|
|
||||||
|
private void HandleFocusOut()
|
||||||
|
{
|
||||||
|
ContentLastFocusOut = DateTime.Now;
|
||||||
|
ContentVisile = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task HandleItemClicked(SelectElement<TItem> selectedValue)
|
||||||
|
{
|
||||||
|
selectedValue.IsSelected = !selectedValue.IsSelected;
|
||||||
|
Values = Items.Where(x => x.IsSelected && x.Item != null).Select(x => x.Item!);
|
||||||
|
Text = string.Join(", ", Values);
|
||||||
|
await ValuesChanged.InvokeAsync(Values);
|
||||||
|
}
|
||||||
|
private void HandleTextChanged(string args)
|
||||||
|
{
|
||||||
|
foreach (var item in Items)
|
||||||
|
{
|
||||||
|
item.IsSelected = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
@import "SelectList.razor.css";
|
||||||
@@ -5,4 +5,5 @@ public class SelectElement<TItem>
|
|||||||
public TItem? Item { get; set; }
|
public TItem? Item { get; set; }
|
||||||
public string? Label { get; set; }
|
public string? Label { get; set; }
|
||||||
public bool IsSelected { get; set; } = false;
|
public bool IsSelected { get; set; } = false;
|
||||||
|
public bool IsNew { get; set; } = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ public partial class SelectList<TItem>
|
|||||||
private void HandleFocusOut()
|
private void HandleFocusOut()
|
||||||
{
|
{
|
||||||
ContentLastFocusOut = DateTime.Now;
|
ContentLastFocusOut = DateTime.Now;
|
||||||
ContentVisile = false;
|
ContentVisile = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task HandleItemClicked(SelectElement<TItem> selectedValue)
|
private async Task HandleItemClicked(SelectElement<TItem> selectedValue)
|
||||||
|
|||||||
Reference in New Issue
Block a user