BlazorSortableList 1.2.0
See the version list below for details.
dotnet add package BlazorSortableList --version 1.2.0
NuGet\Install-Package BlazorSortableList -Version 1.2.0
<PackageReference Include="BlazorSortableList" Version="1.2.0" />
paket add BlazorSortableList --version 1.2.0
#r "nuget: BlazorSortableList, 1.2.0"
// Install BlazorSortableList as a Cake Addin #addin nuget:?package=BlazorSortableList&version=1.2.0 // Install BlazorSortableList as a Cake Tool #tool nuget:?package=BlazorSortableList&version=1.2.0
Blazor Sortable List
Overview
Fork an implementation of the SortableJS library for Blazor. This example shows you how to reorder elements within a list using drag and drop.
Original JS library has more features as implemented now
Great implementation, but I would like to make some changes:
- extract package
- use .NET 8.0 project style for Demo application
- I am thinking of an architecture/usability improvement.
The latest changes will appear first on the development branch.
Compare current implementation with original version:
Prerequisites
Running Locally
- Clone this repository.
- Run the project 'BlazorSortableList.DemoApp' using
dotnet watch
.
How to use it in your own project
- Install the latest NuGet Package
- Using Package Manager
Install-Package BlazorSortableList
- Using .NET CLI
dotnet add package BlazorSortableList
- Using MS VS Manage NuGet Packages search for
BlazorSortableList
- Add SortableJS to your
index.html
/app.razor
file. You can either download from the SortableJS website or use a CDN...
<script src="https://cdn.jsdelivr.net/npm/sortablejs@latest/Sortable.min.js"></script>
- Add the
SortableList.razor.js
to yourindex.html
/'app.razor' file..
<script type="module" src="_content/BlazorSortableList/SortableList.razor.js"></script>
Add the SortableList component to your page and define the SortableItemTemplate...
<SortableList Id="sortable" Items="items" OnUpdate="@SortList" Context="item"> <SortableItemTemplate> <div> <p>@item.Name</p> </div> </SortableItemTemplate> </SortableList>
- Items: The list of items to be displayed. Can be of any type.
- OnUpdate: The method to be called when the list is updated.
- Context: The name of the variable to be used in the template.
The SortableItemTemplate
can contain any markup or components that you want.
Attributes
Properties
All properties are optional and have default values.
Name | Type | Default | Ver. | Description |
---|---|---|---|---|
Id | String | new GUID | 1.0 | The id of the HTML element that will be turned into a sortable list. If you don't supply this, a random id (GUID) will be generated for you |
Group | String | new GUID | 1.0 | Used for dragging between lists. Set the group to the same value on both lists to enable |
Pull | String | null | 1.0 | Used when you want to clone elments into a list instead of moving them. Set Pull to "clone" |
Put | Boolean | true | 1.0 | Set to false to disable dropping from another list onto the current list |
Sort | Boolean | true | 1.0 | Disable sorting within a list by setting to false |
Handle | String | "" | 1.0 | The CSS class you want the sortable to respect as the drag handle |
Filter | String | "" | 1.0 | The CSS class you want to use to identify elements that cannot be sorted or moved |
ForceFallback | Boolean | true | 1.0 | Enable HTML5 drag and drop by setting to false |
DefaultSort | Boolean | false | 1.1 | Enable simplified use by setting to true . |
GroupModel | ISortableListGroup<T> | false | 1.2 | Data management class |
Note: Pay attention to the fact that you have to declare the handle in your code. You can only drag an item using the handle. For this example, you need to set
Handle
to ".drag-handle".
<div class="has-cursor-grab">
<div class="drag-handle mr-4">
<i class="is-size-4 fas fa-grip-vertical"></i>
</div>
</div>
Events
OnUpdate
(Optional): The method to be called when the list is updated. You can name this method whatever you like, but it expects a oldIndex
and newIndex
parameters when the drag and drop occurs.
OnRemove
(Optional): The method to be called when an item is removed from a list. This method is useful for handling the drop even between multiple lists. Like OnUpdate
, it expects oldIndex
and newIndex
parameters.
You will need to handle all events yourself. If you don't handle any events, no sort or move will happen as Blazor needs to make the changes to the underlying data structures so it can re-render the list.
Here is an example of how to reorder your list when the OnUpdate is fired...
Razor
<SortableList Id="simpleList" Items="items" OnUpdate="@SortList" Context="item">
<SortableItemTemplate>
<div class="card has-border-light has-background-blazor has-text-white has-cursor-grab">
<p class="is-size-4 p-2 ml-4">@item.Name</p>
</div>
</SortableItemTemplate>
</SortableList>
C#
private List<Item> items = Enumerable.Range(1, 10).Select(i => new Item { Id = i, Name = $"Item {i}" }).ToList();
private void SortList((int oldIndex, int newIndex) indices)
{
var (oldIndex, newIndex) = indices;
var items = this.items;
var itemToMove = items[oldIndex];
items.RemoveAt(oldIndex);
if (newIndex < items.Count)
{
items.Insert(newIndex, itemToMove);
}
else
{
items.Add(itemToMove);
}
StateHasChanged();
}
Enhanced version
Version 1.1
From version 1.1 It is possible to use simplified code.
Razor
<SortableList Items="items" Context="item" DefaultSort>
<SortableItemTemplate>
<div class="card has-border-light has-background-blazor has-text-white has-cursor-grab">
<p class="is-size-4 p-2 ml-4">@item.Name</p>
</div>
</SortableItemTemplate>
</SortableList>
No additional C# code required.
Version 1.2
I am trying to move all the logic to external classes because I want to use the dumb UI.
The main idea is that all lists in the group use the same "data" class. This class received all notifications and manipulated the real data elements (fig.1 - custom sorting group, fig.3 SharedSortableListGroup). Each list must have its own settings. Each list must have its own settings. Settings and data (fig.1 - SortableListModel) are accessible via list id. Make sure you use the same id for the list control and the data insert.
fig.1
fig.2
fig.3
You can now compare 2 implementations, old and new: Razor
<SortableList Id="@ListId" GroupModel="@_group" Context="item">
<SortableItemTemplate>
<div class="card has-border-light has-background-blazor1 has-cursor-grab">
<p class="is-size-4 p-2 ml-4">@item.Name</p>
</div>
</SortableItemTemplate>
</SortableList>
C#
private const string ListId = "ExampleListId";
private List<Item> items = Enumerable.Range(1, 10).Select(i => new Item { Id = i, Name = $"Item {i}" }).ToList();
private SingleSortableListGroup<Item> _group;
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
_group = new SingleSortableListGroup<Item>(ListId, new SortableListModel<Item>(items));
}
There are two default generic implementations, SingleSortableListGroup
and TwoSortableListGroup
.
Both implement standard operations for single list and group of two lists (see demo application for details).
Properties of the SortableListSettings
Class
Name | Similar name in Component | Type | Default | Ver. | Description |
---|---|---|---|---|---|
CloneMode | Pull | Boolean | false | 1.2 | Used when you want to clone elments into a list instead of moving them. |
AllowDrop | Put | Boolean | true | 1.2 | Set to false to disable dropping from another list onto the current list |
AllowReorder | Sort | Boolean | true | 1.2 | Disable sorting within a list by setting to false |
CssForDragHandle | Handle | String | "" | 1.2 | The CSS class you want the sortable to respect as the drag handle |
CssForDisabledItem | Filter | String | "" | 1.2 | The CSS class you want to use to identify elements that cannot be sorted or moved |
AllowHtml5DragAndDrop | ForceFallback | Boolean | false | 1.2 | Enable HTML5 drag and drop |
Example of how to use the settings
ClonedSortableListGroup _group;
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
SortableListSettings settings = new SortableListSettings() { CloneMode = true };
_group = new ClonedSortableListGroup(ListId1, ListId2, () => StateHasChanged());
_group.AddModel(ListId1, new SortableListModel<Item>(items1) { Group = GroupId, Settings = settings });
_group.AddModel(ListId2, new SortableListModel<Item>(items2) { Group = GroupId, Settings = settings });
}
History
V1.2 - addition of data abstraction classes
V1.1 - added DefaultSort parameter
V1.0 - orignal component
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
-
net8.0
- Microsoft.AspNetCore.Components.Web (>= 8.0.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.