A Blazor component that wraps the SortableJS library, designed for creating interactive sortable lists with drag-and-drop support. Inspired by BlazorSortable and represents an improved and extended implementation.
dotnet add package BlazorSortableAdd to your .csproj file:
<ItemGroup>
<PackageReference Include="BlazorSortable" Version="5.*" />
</ItemGroup>-
Add the SortableJS library to:
wwwroot/index.html(for Blazor WebAssembly)Components/App.razor(for Blazor Web App)Pages/_Host.cshtml(for Blazor Server)
Using one of the following methods:
a) Via CDN:
<script src="https://cdn.jsdelivr.net/npm/sortablejs@latest/Sortable.min.js"></script>
b) Locally:
<script src="lib/sortable/dist/js/Sortable.min.js"></script>
You can optionally include a version parameter to avoid browser caching:
<script src="lib/sortable/dist/js/Sortable.min.js?v=1.15.6"></script>
For local installation:
- Download the latest version of SortableJS from GitHub
- Create the folder structure in
wwwroot:lib/sortable/dist/js/ - Place the
Sortable.min.jsfile in the created folder
-
(Optional) Add base styles to the same file where you added the script:
<link rel="stylesheet" href="_content/BlazorSortable/css/blazor-sortable.css" />You can also specify the version manually to prevent browser caching:
<link rel="stylesheet" href="_content/BlazorSortable/css/blazor-sortable.css?v=5.1.3" />Or automatically insert the current assembly version (works in
.razoror.cshtmlfiles). Add this code within the<head>element, or for Blazor WebAssembly, place it inside the<HeadContent>section ofApp.razor:<link rel="stylesheet" href="_content/BlazorSortable/css/blazor-sortable.css?v=@(typeof(BlazorSortable.Sortable<>).Assembly.GetName().Version)" />For this to work in Blazor WebAssembly, make sure you have the following line in your
Program.cs:builder.RootComponents.Add<HeadOutlet>("head::after");
- Add services in
Program.cs:
using BlazorSortable;
// ...
builder.Services.AddSortable();- Add the using directive in
_Imports.razor:
@using BlazorSortable<Sortable Items="Persons"
Class="my-sortable"
Group="group1">
<PersonComponent Person="context" />
</Sortable><Sortable TItem="Person"
Items="Persons"
Class="my-sortable"
Group="group1"
Context="person">
<div class="person-card">
<h4>@person.Name</h4>
<p>@person.Email</p>
<span class="badge">@person.Department</span>
</div>
</Sortable><Sortable TItem="object"
Class="my-sortable-drop-zone"
Group="group1" />Note: Support for MultiDrag and Swap plugins will be added in future releases.
| Parameter | Type | Default | Description |
|---|---|---|---|
TItem |
— | — | The type of items in the list |
Items |
IList<TItem>? |
null |
List of items to display and sort |
ChildContent |
RenderFragment<TItem>? |
null |
Template for displaying each list item. Can be a component, HTML elements, or any Razor markup |
KeySelector |
Func<TItem, object>? |
null |
Function for generating the key used in @key. If not set, the item itself is used |
Context |
string |
context |
Name of the parameter used in the child content template to refer to the current item |
Class |
string? |
null |
CSS class for the container |
Style |
string? |
null |
Inline CSS styles for the container |
Attributes |
IReadOnlyDictionary<string, object>? |
null |
Additional custom attributes that will be rendered by the component |
Id |
string |
Random GUID |
Unique identifier of the component. Used internally for coordination between Sortable components. Must be globally unique |
Group |
string |
Random GUID |
Name of the group for interacting with other sortable instances |
Pull |
SortablePullMode? |
null |
Mode for pulling items from the list |
PullGroups |
string[]? |
null |
Required when Pull="SortablePullMode.Groups". Specifies the groups into which items from this list can be dragged |
CloneFunction |
Func<TItem, TItem>? |
null |
Required when Pull="SortablePullMode.Clone". A factory method used to create a clone of the dragged item |
PullFunction |
Predicate<SortableTransferContext<TItem>>? |
null |
Required when Pull="SortablePullMode.Function". Function to determine if an item can be pulled to the target Sortable component |
Put |
SortablePutMode? |
null |
Mode for adding items to the list |
PutGroups |
string[]? |
null |
Required when Put="SortablePutMode.Groups". Specifies the groups from which items are allowed to be added |
PutFunction |
Predicate<SortableTransferContext<object>>? |
null |
Required when Put="SortablePutMode.Function". Function to determine if an item can be put into this list |
ConvertFunction |
Func<SortableTransferContext<object>, TItem?>? |
null |
Function to convert items from other Sortable component to the target type |
Sort |
bool |
true |
Enables or disables sorting of items within the list |
Delay |
int |
0 |
Time in milliseconds to define when the sorting should start. Unfortunately, due to browser restrictions, delaying is not possible on IE or Edge with native drag and drop |
DelayOnTouchOnly |
bool |
false |
Whether or not the delay should be applied only if the user is using touch (eg. on a mobile device). No delay will be applied in any other case |
TouchStartThreshold |
int |
0 |
This option sets the minimum pointer movement that must occur before the delayed sorting is cancelled. Values between 3 to 5 are good |
Disabled |
bool |
false |
Disables the Sortable component when set to true |
Animation |
int |
150 |
Animation duration in milliseconds |
Handle |
string? |
null |
CSS selector for elements that can be dragged (e.g. .my-handle) |
Filter |
string? |
null |
CSS selector for elements that cannot be dragged (e.g. .ignore-elements) |
DraggableSelector |
Predicate<TItem>? |
null |
Function to determine if an item can be dragged |
DraggableClass |
string |
"sortable-draggable" |
CSS class applied to items that can be dragged |
GhostClass |
string |
"sortable-ghost" |
CSS class for the placeholder during drag |
ChosenClass |
string |
"sortable-chosen" |
CSS class for the chosen element |
DragClass |
string |
"sortable-drag" |
CSS class for the dragged element |
SwapThreshold |
double |
1 |
Percentage of the target that the swap zone will take up, as a float between 0 and 1 |
InvertSwap |
bool |
false |
Set to true to set the swap zone to the sides of the target, for the effect of sorting "in between" items |
InvertedSwapThreshold |
double |
1 |
Percentage of the target that the inverted swap zone will take up, as a float between 0 and 1 |
ForceFallback |
bool |
true |
If set to true, the Fallback for non HTML5 Browser will be used, even if we are using an HTML5 Browser |
FallbackClass |
string |
"sortable-fallback" |
CSS class for the element in fallback mode |
FallbackOnBody |
bool |
false |
Appends the cloned DOM Element into the Document's Body |
FallbackTolerance |
int |
0 |
Emulates the native drag threshold. Specify in pixels how far the mouse should move before it's considered as a drag. 3 to 5 are probably good values |
Scroll |
bool |
true |
Enables scrolling of the container during dragging |
OnUpdate |
Action<SortableEventArgs<TItem>>? |
null |
Raised when the order of items is changed |
OnAdd |
Action<SortableEventArgs<TItem>>? |
null |
Raised when an item is added to the list |
OnRemove |
Action<SortableEventArgs<TItem>>? |
null |
Raised when an item is removed from the list |
| Value | Description |
|---|---|
True |
Allows pulling items from the list |
False |
Prohibits pulling items from the list |
Groups |
Allows pulling items only from specified groups (requires PullGroups parameter) |
Clone |
Creates a clone of the item when dragging (requires CloneFunction parameter) |
Function |
Uses a custom function to determine if items can be pulled (requires PullFunction parameter) |
| Value | Description |
|---|---|
True |
Allows adding items to the list |
False |
Prohibits adding items to the list |
Groups |
Allows adding items only from specified groups (requires PutGroups parameter) |
Function |
Uses a custom function to determine if items can be added (requires PutFunction parameter) |
All events receive a SortableEventArgs<TItem> parameter.
Functions like PullFunction, PutFunction, and ConvertFunction use a SortableTransferContext<TItem> parameter.
The SortableEventArgs<TItem> class provides information about sorting operations.
| Property | Type | Description |
|---|---|---|
Item |
TItem |
The item participating in the operation |
From |
ISortableInfo |
Source sortable component |
OldIndex |
int |
The previous index of the item in the source sortable |
To |
ISortableInfo |
Target sortable component |
NewIndex |
int |
The new index of the item in the target sortable |
IsClone |
bool |
Flag indicating whether the item is a clone |
The SortableTransferContext<TItem> class represents the context of transferring an item between sortable components.
| Property | Type | Description |
|---|---|---|
Item |
TItem |
The item being transferred between sortable components |
From |
ISortableInfo |
The source sortable component |
To |
ISortableInfo |
The target sortable component |
The ISortableInfo interface provides information about a sortable component.
| Property | Type | Description |
|---|---|---|
Id |
string |
Unique identifier of the component |
Group |
string |
Group name for interaction with other Sortable components |
-
Order of events when dragging between lists:
OnAddis triggered first — during this event, the item is still present in the source list.OnRemoveis triggered after.
-
Events use
Action<T>?instead ofEventCallback<T>.
Reason:EventCallback.InvokeAsyncautomatically triggersStateHasChangedin the parent component, which causes conflicts between the DOM and the data model for this component. -
Type mismatch / failed conversion:
If item types don’t match or theConvertFunctionreturnsnull, the item is not added to the target list and is remains in its original position. -
Dragging issues on scrolled page:
If the dragged element appears misaligned when the page is scrolled, setForceFallback="false"
or
FallbackOnBody="true"