From b250353ad8cd5a4417b2574ef26567838698193d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20Ko=C5=BEelj?= Date: Wed, 15 Mar 2023 10:35:13 +0100 Subject: [PATCH] Add dropdown component --- .../Components/Dropdown.razor | 48 ++++++++ .../Components/Dropdown.razor.cs | 112 ++++++++++++++++++ 2 files changed, 160 insertions(+) create mode 100644 src/Connected.Components/Components/Dropdown.razor create mode 100644 src/Connected.Components/Components/Dropdown.razor.cs diff --git a/src/Connected.Components/Components/Dropdown.razor b/src/Connected.Components/Components/Dropdown.razor new file mode 100644 index 0000000..99a445e --- /dev/null +++ b/src/Connected.Components/Components/Dropdown.razor @@ -0,0 +1,48 @@ +@typeparam T; +@inherits Connected.Models.InputBase; + +
+ + + + + + +
@HelperText
+
@ErrorText
+ + + + + + + + + + + + + +
+
+ +
+
\ No newline at end of file diff --git a/src/Connected.Components/Components/Dropdown.razor.cs b/src/Connected.Components/Components/Dropdown.razor.cs new file mode 100644 index 0000000..2c2780c --- /dev/null +++ b/src/Connected.Components/Components/Dropdown.razor.cs @@ -0,0 +1,112 @@ +using Microsoft.AspNetCore.Components; +using System.Collections.ObjectModel; +using Connected.Models; +using System.Collections.Immutable; + +namespace Connected.Components; + +public partial class Dropdown : InputBase, IAsyncDisposable +{ + [Parameter, EditorRequired] + public ObservableCollection Items { get; set; } = new ObservableCollection(); + + [Parameter] + public RenderFragment? OptionTemplate { get; set; } + + [Parameter] + public RenderFragment? SelectedValueTemplate { get; set; } + + [Parameter, EditorRequired] + public Func ItemToKey { get; set; } = default!; + + [Parameter] + public ObservableCollection SelectedItems { get; set; } = new(); + + [Parameter] + public EventCallback> SelectedItemsChanged { get; set; } + + [Parameter] + public bool AllowMultiple { get; set; } + + private bool DropdownOpen { get; set; } + + private bool IsItemSelected(T item) + { + return SelectedItems.Contains(item); + } + + public void Open() + { + DropdownOpen = true; + } + + public void Close() + { + DropdownOpen = false; + } + + public void Toggle() + { + DropdownOpen = !DropdownOpen; + } + + protected override void OnInitialized() + { + base.OnInitialized(); + + OptionTemplate ??= (T item) => (builder) => + { + builder.OpenElement(0, "div"); + builder.SetKey(item); + builder.AddContent(1, item?.ToString()); + builder.CloseElement(); + }; + + SelectedValueTemplate ??= (T item) => (builder) => + { + builder.OpenElement(0, "span"); + builder.SetKey(item); + builder.AddContent(1, item?.ToString()); + builder.CloseElement(); + }; + } + protected override void OnParametersSet() + { + base.OnParametersSet(); + + Items.CollectionChanged += CollectionChanged; + SelectedItems.CollectionChanged += CollectionChanged; + } + + private void CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) + { + if (sender == SelectedItems) + SelectedItemsChanged.InvokeAsync(SelectedItems); + + StateHasChanged(); + } + + private async Task OptionSelected(T item) + { + if (AllowMultiple) + { + if (SelectedItems.Contains(item)) + { + SelectedItems.Remove(item); + return; + } + } + else + { + SelectedItems.Clear(); + } + + SelectedItems.Add(item); + } + + public async ValueTask DisposeAsync() + { + Items.CollectionChanged -= CollectionChanged; + SelectedItems.CollectionChanged -= CollectionChanged; + } +} \ No newline at end of file