New DataList component

This commit is contained in:
Pat Hartl 2025-11-10 18:07:13 -06:00
parent 37eebfde9c
commit 28f76be108
4 changed files with 148 additions and 3 deletions

View file

@ -0,0 +1,65 @@
@namespace LANCommander.UI.Components
@typeparam TItem
<div class="data-list">
<CascadingValue Value="_radio" Name="Radio">
<CascadingValue Value="_checkbox" Name="Checkbox">
@foreach (var item in DataSource)
{
<CascadingValue Value="@(Value.Equals(item) || Values.Contains(item))" Name="Selected">
<DataListItem
Item="item"
OnSelectedChanged="(selected) => SelectionChanged(item, selected)"
ItemTemplate="ChildContent" />
</CascadingValue>
}
</CascadingValue>
</CascadingValue>
</div>
@code {
[Parameter] public IEnumerable<TItem> DataSource { get; set; }
[Parameter] public TItem Value { get; set; }
[Parameter] public EventCallback<TItem> ValueChanged { get; set; }
[Parameter] public IEnumerable<TItem> Values { get; set; }
[Parameter] public EventCallback<IEnumerable<TItem>> ValuesChanged { get; set; }
[Parameter] public RenderFragment<TItem> ChildContent { get; set; }
[Parameter] public RenderFragment<TItem> ItemTemplate { get; set; }
bool _radio;
bool _checkbox;
List<TItem> _selectedValues = new();
protected override void OnInitialized()
{
if (ValueChanged.HasDelegate)
_radio = true;
else if (ValuesChanged.HasDelegate)
_checkbox = true;
if (ChildContent == null && ItemTemplate != null)
ChildContent = ItemTemplate;
}
async Task SelectionChanged(TItem item, bool selected)
{
if (_radio && selected)
{
Value = item;
await ValueChanged.InvokeAsync(Value);
}
else if (_checkbox)
{
_selectedValues.Remove(item);
if (selected)
_selectedValues.Add(item);
Values = _selectedValues;
await ValuesChanged.InvokeAsync(Values);
}
}
}

View file

@ -1,6 +1,7 @@
namespace LANCommander.UI.Components.DataList;
namespace LANCommander.UI.Components;
public class DataListInputPosition
public enum DataListInputPosition
{
Left,
Right,
}

View file

@ -0,0 +1,48 @@
@namespace LANCommander.UI.Components
@typeparam TItem
<CascadingValue Value="Item" Name="Item">
<Flex @onclick="ToggleSelection" Align="Align" Justify="Justify" Gap="Gap" Class="data-list-item">
@if (InputPosition == DataListInputPosition.Left)
{
<DataListItemInput />
}
@ItemTemplate(Item)
@if (InputPosition == DataListInputPosition.Right)
{
<DataListItemInput />
}
</Flex>
</CascadingValue>
@code {
[CascadingParameter(Name = "Selected")]
public bool Selected { get; set; }
[CascadingParameter(Name = "Radio")]
public bool Radio { get; set; }
[CascadingParameter(Name = "Checkbox")]
public bool Checkbox { get; set; }
[CascadingParameter(Name = "InputPosition")]
public DataListInputPosition InputPosition { get; set; }
[CascadingParameter(Name = "SelectionTemplate")]
public RenderFragment<TItem> SelectionTemplate { get; set; }
[Parameter] public TItem Item { get; set; }
[Parameter] public RenderFragment<TItem> ItemTemplate { get; set; }
[Parameter] public EventCallback<bool> OnSelectedChanged { get; set; }
[Parameter] public FlexAlign Align { get; set; } = FlexAlign.Normal;
[Parameter] public FlexJustify Justify { get; set; } = FlexJustify.Center;
[Parameter] public FlexGap Gap { get; set; } = FlexGap.Normal;
private async Task ToggleSelection()
{
if (OnSelectedChanged.HasDelegate)
await OnSelectedChanged.InvokeAsync(!Selected);
}
}

View file

@ -0,0 +1,31 @@
@namespace LANCommander.UI.Components
@typeparam TItem
@if (SelectionTemplate != null)
{
@SelectionTemplate((Item, Selected))
}
else if (Radio)
{
<Radio Checked="Selected"></Radio>
}
else if (Checkbox)
{
<Checkbox Checked="Selected"></Checkbox>
}
@code {
[CascadingParameter(Name = "Item")]
public TItem Item { get; set; }
[CascadingParameter(Name = "Selected")]
public bool Selected { get; set; }
[CascadingParameter(Name = "Radio")]
public bool Radio { get; set; }
[CascadingParameter(Name = "Checkbox")]
public bool Checkbox { get; set; }
[Parameter] public RenderFragment<(TItem, bool)> SelectionTemplate { get; set; }
}