Hi.
I have need in my app for a means to select items from available lists in more than one place, which I would like to do with two listboxes which you can drag/drop items between.
I can do this following the example here: https://blazor.syncfusion.com/demos/listbox/drag-and-drop?theme=fluent
however, since I want to do this in a few places, with lists of different types of objects, I want to encapsulate this in a re-usable component.
I have managed to basically achieve this with this component:
---------------------------------------
@typeparam TItem
@using Syncfusion.Blazor.DropDowns;
@using Syncfusion.Blazor.Lists
<div id="drag-drop-wrapper">
<div class="listbox-control left-box">
<h5>Available</h5>
<SfListBox
DataSource="@ItemList"
Scope="@Scope"
TItem="TItem"
AllowDragAndDrop="true"
Height="330px"
TValue="TItem"
NoRecordsTemplate="NoRecs()"
>
<ItemTemplate>
@GetItemTemplate(context)
</ItemTemplate>
</SfListBox>
</div>
<span class="e-swap-icon"></span>
<div class="listbox-control right-box">
<h5>Selected</h5>
<SfListBox
DataSource="@SelectedList"
Scope="@Scope"
TItem="TItem"
AllowDragAndDrop="true"
Height="330px"
TValue="TItem"
NoRecordsTemplate="NoRecs()"
@onchange="ChangeSelected"
>
<ItemTemplate>
@GetItemTemplate(context)
</ItemTemplate>
</SfListBox>
</div>
</div>
@code {
[Parameter]
public string? Scope{ get; set; }
[Parameter]
public IEnumerable<TItem>? ItemList{ get; set; }
[Parameter]
public List<TItem>? SelectedList { get; set; }
[Parameter]
public RenderFragment<TItem>? ItemTemplate { get; set; }
[Parameter]
public Func<TItem, string> GetDisplayItem { get; set; }
[Parameter]
public EventCallback<List<TItem>> SelectedListChanged{ get; set; }
[Parameter]
public string? NoItemsText { get; set; }
async Task ChangeSelected()
{
await SelectedListChanged.InvokeAsync(SelectedList);
}
RenderFragment NoRecs() => builder =>
{
builder.AddContent(1, NoItemsText ?? "No Items Selected");
};
RenderFragment GetItemTemplate(TItem context) => builder =>
{
builder.AddContent(1, GetDisplayItem(context));
};
}
-----------------------
And it is used like this in a page:
--------------------------------------
<DragDropListSelector
@bind-SelectedList="@Selected"
ItemList="@Available"
NoItemsText="nothing here"
Scope="group-fields-scope"
TItem="CountryCode"
GetDisplayItem="x=>x.Name">
</DragDropListSelector>
-------------------------
And it almost works - it shows the lists OK, and you can pick up to drag items... but you can't drop the items (it just gets ignored)
I'm not sure what I've done wrong here - is it due to my use of ItemTemplate rather than ListBoxFieldSettings?
I have attached a minimal example solution which implements a "working" example as per the demo and under that a non-working equivalent using my component version.
Can anyone let me know where I've gone wrong here?
We have validated the attached sample and found an issue in your code.
TItem and TValue would miss-match in Index and DragDropListSelector file. And we need to set the field setting for the list box. Refer to the below code snippet.
<SfListBox DataSource="@ItemList" Scope="@Scope" TItem="CountryCode" AllowDragAndDrop="true" Height="330px" TValue="string[]" NoRecordsTemplate="NoRecs()" > <ListBoxFieldSettings Text="Name" Value="Code"> </ListBoxFieldSettings> <ListBoxTemplates TItem="CountryCode"> <ItemTemplate> @GetItemTemplate(context) </ItemTemplate> </ListBoxTemplates> </SfListBox> |