DropZoneGroup
Since 0.1.0-alpha.20Static server-side rendering: no circuit, no WebAssembly.
Moves items between lists: a board's columns, a list of available items and a list of chosen ones. The group holds the items and saves the moves; each zone is a ListView with a Zone, placed anywhere in the group's content, which shows the group's items in that zone and keeps every ListView option (a template, ItemMenu, ItemActions, ItemHref).
Usage
<DropZoneGroup @bind-Items="tasks" ItemKey="t => t.Id" ZoneOf="t => t.Status" OnMove="Moved">
<Grid Columns="3">
<ListView Zone="todo" AriaLabel="To do" Context="task">task.Title</ListView>
<ListView Zone="doing" AriaLabel="Doing" MaxItems="3" Context="task">task.Title</ListView>
<ListView Zone="done" AriaLabel="Done" Accepts="t => t.Reviewed" Context="task">task.Title</ListView>
</Grid>
</DropZoneGroup>
{
Task Moved(ListMoveEventArgs<TaskItem> move)
{
move.Item.Status = move.ToZone!;
return db.SaveAsync();
}
}A board
Put a ListView with a Zone in the group for each column, anywhere in its layout; Cards draws its items as cards. The group holds the items, and ZoneOf says which zone each is in. On an interactive page @bind-Items keeps the order, and OnMove (with FromZone and ToZone) is where you save a move. On a static page give the group a Name and pass the posted ListOrder back as Order; SubmitOnMove posts each move, and Order.Arrange gives each item's zone and place to save. Accepts and MaxItems limit what a zone takes; the Kanban board demo shows them with cards that drag from anywhere.
Preview
Code
@* Each column is a ListView with a Zone; the group holds every task and ZoneOf says which column
it's in. On a static page every move posts the form (SubmitOnMove) and Order shows it. *@
<Stack Grow>
<Form Model="this" FormName="drop-zone-board">
<DropZoneGroup @bind-Items="_tasks" ItemKey="t => t.Id" ZoneOf="t => t.Status" Name="board" Order="Order" SubmitOnMove>
<Grid Columns="new() { Base = 1, Md = 3 }" Gap="3">
foreach (var (zone, label) in Columns)
{
<Stack Gap="3" Padding="3" Bg="Color.SurfaceSunken" Radius="Radius.Lg">
<Heading Level="3" Size="TextSize.Md">label</Heading>
<ListView Zone="zone" AriaLabel="label" Cards ItemText="t => t.Title" Size="ControlSize.Sm" />
</Stack>
}
</Grid>
</DropZoneGroup>
</Form>
</Stack>
{
[SupplyParameterFromForm(FormName = "drop-zone-board", Name = "board")]
private ListOrder? Order { get; set; }
private static readonly (string Zone, string Label)[] Columns = [("todo", "To do"), ("doing", "Doing"), ("done", "Done")];
private IReadOnlyList<BoardTask> _tasks =
[
new("1", "Write the brief", "todo"),
new("2", "Pick a venue", "todo"),
new("3", "Book the speakers", "doing"),
new("4", "Set the date", "done"),
];
}Static: Drag a handle into another column, or use its menu: the task moves, the move is announced, and the form posts.
Details
Items drag within their zone and to another one that accepts them and has room; the menu of moves (the handle's, or the ⋯ menu's Move submenu) adds "Move to" and each such zone. On a static page give the group a Name inside a form and pass the posted ListOrder back as Order.
Mode support
| Feature | Static | Interactive |
|---|---|---|
| Moving between zones from each handle's menu (with script off, each move posts the form) | Yes | Yes |
| Dragging between zones and announcements | Yes | Yes |
| The moves bound to C# | No | Yes |
Static: static server-side rendering, with no circuit and no WebAssembly. Interactive: Server, WebAssembly or Auto.
Without JavaScript
Every page starts as plain HTML: before IzzyBlazor's script loads on a static page, while an interactive page prerenders, and with JavaScript off.
- Dragging between zones and announcements: waits for the script
Accessibility
- Each zone is a list named by its AriaLabel (give every zone one), which also names it in the menu ("Move to Done").
- A move is announced from the zone it lands in: "Moved Ada to Done, position 1 of 3".
Parameters
| Prop | Type | Default |
|---|---|---|
@bind-ItemsEvery item, in every zone; each zone shows its own in this order. | IEnumerable<TItem>? | Required |
ItemKeyEach item's key: what posts and what keeps its elements when it moves. | Func<TItem, string>? | Required |
ZoneOfThe zone an item is in, matching a ListView's Zone, such as t => t.Status. | Func<TItem, string>? | Required |
NameOn a static page, the prefix of the fields the zones post: {Name}.Keys, {Name}.Zones and {Name}.Move, bound as a ListOrder. | string? | |
OrderOn a static page, what the form posted: the zones show the posted order and zones with the move applied, and focus the moved item's handle (or ⋯ button). | ListOrder? | |
SubmitOnMoveOn a static page with script, posts the form after each move, for pages that save every move. | bool | false |
ChildContentThe layout: the zones (ListViews with a Zone) in a Grid, a Stack or Cards. | RenderFragment? | |
OnMoveRuns before a move changes the zones, on interactive pages: set the item's zone from ToZone and save it here, or set Cancel to keep the item where it was. | EventCallback<ListMoveEventArgs<TItem>> |
Plus 4 common props.
Full APISee also
- ListView: items from data, each drawn by a template; links, selection, reordering and paging.
- Demos: Kanban board.