Skip to content

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.Bortable

A 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" };
}
Live
Write the spec
Review the PR
Ship it

Order: Write the spec, Review the PR, Ship it

The list must be mutable - a List<T> or anything else whose IsReadOnly is false. Items are rendered with @key, so they must be unique within a list.
An unhandled error has occurred. Reload 🗙