features/rewrite/dropdown #14
							
								
								
									
										48
									
								
								src/Connected.Components/Components/Dropdown.razor
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/Connected.Components/Components/Dropdown.razor
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,48 @@
 | 
			
		||||
@typeparam T;
 | 
			
		||||
@inherits Connected.Models.InputBase;
 | 
			
		||||
 | 
			
		||||
<div class="@InputFieldClassList">
 | 
			
		||||
   <select type="textarea" @onfocus="(()=> Open())" @onblur="(()=> Close())">
 | 
			
		||||
      @if (SelectedItems.Any())
 | 
			
		||||
      {
 | 
			
		||||
         <option selected>
 | 
			
		||||
            @foreach (var item in SelectedItems)
 | 
			
		||||
            {
 | 
			
		||||
               @SelectedValueTemplate?.Invoke(item)
 | 
			
		||||
            }
 | 
			
		||||
         </option>
 | 
			
		||||
      }
 | 
			
		||||
   </select>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   <span class="highlight"></span><span class="bar"></span>
 | 
			
		||||
   <label class="label-animated">@Label</label>
 | 
			
		||||
   <div class="input-helper-text">@HelperText</div>
 | 
			
		||||
   <div class="input-error-text">@ErrorText</div>
 | 
			
		||||
   <span class="input-glyph-wraper">
 | 
			
		||||
      <span class="input-glyph button">
 | 
			
		||||
         <Glyph SVG="@Icons.Material.Outlined.Cancel" class="icon-root svg-icon" Click="_ => { SelectedItems.Clear(); Close(); }" />
 | 
			
		||||
      </span>
 | 
			
		||||
      <span class="input-glyph">
 | 
			
		||||
         <Glyph SVG="@Icons.Material.Filled.ArrowDropDown" class="icon-root svg-icon icon-size-md" Click="()=> Toggle()" />
 | 
			
		||||
      </span>
 | 
			
		||||
      <span class="input-glyph error">
 | 
			
		||||
         <Glyph SVG="@Icons.Material.Outlined.ErrorOutline" class="icon-root svg-icon" />
 | 
			
		||||
      </span>
 | 
			
		||||
   </span>
 | 
			
		||||
 | 
			
		||||
   <TransitionAnimator TransitionDuration="5000" TransitionInClass="drop-down fade-in" TransitionOutClass="drop-down fade-out" Visible=@DropdownOpen>
 | 
			
		||||
      <div class="backdrop d-sm-none">
 | 
			
		||||
      </div>
 | 
			
		||||
      <div class="dropdown-menu">
 | 
			
		||||
         @foreach (var item in Items)
 | 
			
		||||
         {
 | 
			
		||||
            <div class="dropdown-item @(IsItemSelected(item)?"active":"")"
 | 
			
		||||
              @onclick="(async () => await OptionSelected(item))">
 | 
			
		||||
               @OptionTemplate?.Invoke(item)
 | 
			
		||||
            </div>
 | 
			
		||||
         }
 | 
			
		||||
      </div>
 | 
			
		||||
   </TransitionAnimator>
 | 
			
		||||
</div>
 | 
			
		||||
							
								
								
									
										112
									
								
								src/Connected.Components/Components/Dropdown.razor.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								src/Connected.Components/Components/Dropdown.razor.cs
									
									
									
									
									
										Normal file
									
								
							@ -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<T> : InputBase, IAsyncDisposable
 | 
			
		||||
{
 | 
			
		||||
	[Parameter, EditorRequired]
 | 
			
		||||
	public ObservableCollection<T> Items { get; set; } = new ObservableCollection<T>();
 | 
			
		||||
 | 
			
		||||
	[Parameter]
 | 
			
		||||
	public RenderFragment<T>? OptionTemplate { get; set; }
 | 
			
		||||
 | 
			
		||||
	[Parameter]
 | 
			
		||||
	public RenderFragment<T>? SelectedValueTemplate { get; set; }
 | 
			
		||||
 | 
			
		||||
	[Parameter, EditorRequired]
 | 
			
		||||
	public Func<T, string> ItemToKey { get; set; } = default!;
 | 
			
		||||
 | 
			
		||||
	[Parameter]
 | 
			
		||||
	public ObservableCollection<T> SelectedItems { get; set; } = new();
 | 
			
		||||
 | 
			
		||||
	[Parameter]
 | 
			
		||||
	public EventCallback<ObservableCollection<T>> 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;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user