Skip to content
IzzyBlazor 0.1.0-alpha.20

Enter all results ↑ ↓ move Esc close

DropZoneGroup

Since 0.1.0-alpha.20
Moves items between lists, such as a board's columns; each zone is a ListView.

Static 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

razor
<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>

@code {
    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

To do

  • Move to
    Write the brief
  • Move to
    Pick a venue
Drop items here No items

Doing

  • Move to
    Book the speakers
Drop items here No items

Done

  • Move to
    Set the date
Drop items here No items

Code

Board.razor
@* 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>

@code {
    [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

What works in each mode, DropZoneGroup
FeatureStaticInteractive
Moving between zones from each handle's menu (with script off, each move posts the form)YesYes
Dragging between zones and announcementsYesYes
The moves bound to C#NoYes

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

DropZoneGroup parameters
PropTypeDefault
@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.boolfalse
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>>

See also

  • ListView: items from data, each drawn by a template; links, selection, reordering and paging.
  • Demos: Kanban board.

Connection lost

Rejoining the server…