Getting started
One package, one service registration and one stylesheet - then any IList<TItem>
on an interactively rendered page becomes a list people can put in order by hand.
Install
In a Blazor Web App with an interactive client, the package belongs in the .Client
project, and the services are registered in both projects - the server prerenders the same
components the client runs.
dotnet add package Bit.Bortable
Register the services
It registers one scoped service: the coordinator that holds the drag in progress, so lists sharing a group can hand an item to each other. Scoped means one per circuit on Blazor Server and one per application on WebAssembly, so two users never share a drag.
// Program.cs - in every project that renders a list
builder.Services.AddBitBortableServices();Reference the stylesheet
It styles the drag states only - the ghost, the chosen item, the hidden original, the swap target, the multi-drag selection - and leaves the look of the list to you. The script module needs no tag: the lists import it on demand, once for all of them.
<link rel="stylesheet" href="_content/Bit.Bortable/bit-bortable.css" />
And the namespace, in _Imports.razor:
@using Bit.BortableA first list
Each item is wrapped in a <div> that carries the drag handlers;
ItemTemplate renders what goes inside it. Class and Style go
to the list container, ItemClass to every item wrapper. @bind-Items keeps
your field in step: the list is changed in place, so the order a user makes is the order your
code reads back.
<Bortable @bind-Items="_items" TItem="string" Class="todo" ItemClass="todo-item"> <ItemTemplate Context="item">@item</ItemTemplate> </Bortable> @code { private IList<string> _items = new List<string> { "Write the spec", "Review the PR", "Ship it" }; }
Order: Write the spec, Review the PR, Ship it
List<T> or anything else whose
IsReadOnly is false. Items are rendered with @key, so they
must be unique within a list.