LgWorkScheduler
LgWorkScheduler<TItem> displays tasks and milestones on a horizontal timeline. It groups items by row, offers multiple timeline granularities, an agenda mode, drag-and-drop, resizing, linked milestones, and custom rendering areas.
<LgWorkScheduler TItem="WorkItem"
Items="_items"
From="_from"
To="_to"
RowField="@(item => item.RowId)" />
- Namespace:
Lagoon.UI.Components - Inherits from:
LgComponentBase - Interfaces:
IFormTrackerComponent,IAsyncDisposable - NuGet package:
Lagoon.UI
This component is designed for a wide workspace and is not suitable for mobile screens.
Usage
Demonstration
Try this component in the Lagoon showcase. A variant oriented toward metric scale is available in the SchedulerVMeters showcase.
Data source
TItem must implement IWorkSchedulerData. From sets the start, To sets the end, and IsVisible allows excluding an item from rendering. If To is null, the item is rendered as a milestone; otherwise it is rendered as a task.
public class WorkItem : IWorkSchedulerData
{
// Identifies the visual row used by RowField.
public int RowId { get; set; }
// Task or milestone start date.
public DateTime? From { get; set; }
// End date; null transforms the item into a milestone.
public DateTime? To { get; set; }
// Allows filtering without removing the item from the collection.
public bool IsVisible { get; set; } = true;
// Business label displayed in custom fragments.
public string LabelKey { get; set; }
// First optional grouping level.
public string GroupKey { get; set; }
// Second optional grouping level.
public string SubGroupKey { get; set; }
}
Simple schedule
Define Items, From, To, and RowField. Without custom fragments, tasks use ToString() and milestones use DefaultJalonCssClass.
<LgWorkScheduler TItem="WorkItem"
Items="_items"
From="_from"
To="_to"
Timeline="TimelineMode.MonthDay"
RowField="@(item => item.RowId)" />
public partial class WorkSchedulerPage : LgPage
{
// Start bound displayed by the schedule.
private DateTime _from = new(2025, 1, 1);
// End bound displayed by the schedule.
private DateTime _to = new(2025, 1, 31);
// Data displayed: one task and one milestone on two rows.
private List<WorkItem> _items = new()
{
new() { RowId = 1, From = new DateTime(2025, 1, 3), To = new DateTime(2025, 1, 8), LabelKey = "#WksTaskA" },
new() { RowId = 2, From = new DateTime(2025, 1, 10), To = null, LabelKey = "#WksMilestone" }
};
}
Customize rows and tasks
ProjectItems customizes the left-side list. SchedulerItems customizes the bars and milestones in the schedule area.
<LgWorkScheduler TItem="WorkItem"
Items="_items"
From="_from"
To="_to"
RowField="@(item => item.RowId)">
<ProjectItems Context="item">
<LgLabel Text="@item.LabelKey" />
</ProjectItems>
<SchedulerItems Context="item">
<div class="w-100 h-100 text-center custom-work-item">
@item.LabelKey.Translate()
</div>
</SchedulerItems>
</LgWorkScheduler>
Milestones
An item with To set to null is a milestone. By default, DefaultJalonCssClass is wk-milestone-square. The component also provides wk-milestone-arrow-up. You can define a custom class and use it in SchedulerItems.
<LgWorkScheduler TItem="WorkItem"
Items="_items"
From="_from"
To="_to"
DefaultJalonCssClass="custom-milestone-circle"
RowField="@(item => item.RowId)" />
.custom-milestone-circle {
width: 20px;
height: 20px;
border-radius: 50%;
background: yellow;
border: 1px solid black;
}
Group rows
GroupBy adds one or more grouping levels. ProjectItemsGroup and SchedulerItemsGroup customize the rendering of groups.
<LgWorkScheduler TItem="WorkItem"
Items="_items"
From="_from"
To="_to"
RowField="@(item => item.RowId)"
GroupBy="_groupBy"
DefaultGroupsState="GroupState.Open">
<ProjectItemsGroup Context="group">
<LgLabel Text="@group.Key?.ToString()" />
</ProjectItemsGroup>
</LgWorkScheduler>
public partial class WorkSchedulerGroupPage : LgPage
{
// Groups rows by business family, then by subfamily.
private List<Func<WorkItem, object>> _groupBy = new()
{
item => item.GroupKey,
item => item.SubGroupKey
};
}
Filter items
The component does not provide a built-in filter like LgGridView. Filter your data by updating IsVisible.
<LgTextBox @bind-Value="_filterText" Label="#WksFilter" OnChange="FilterItemsAsync" />
<LgWorkScheduler TItem="WorkItem"
Items="_items"
From="_from"
To="_to"
RowField="@(item => item.RowId)" />
public partial class WorkSchedulerFilterPage : LgPage
{
// Text entered by the user to filter displayed rows.
private string _filterText;
// Applies the filter while keeping objects in the data source.
private Task FilterItemsAsync(ChangeEventArgs args)
{
string filter = args.Value?.ToString() ?? string.Empty;
foreach (WorkItem item in _items)
{
item.IsVisible = string.IsNullOrWhiteSpace(filter) || item.LabelKey.Contains(filter, StringComparison.OrdinalIgnoreCase);
}
return Task.CompletedTask;
}
}
Drag-and-drop and resizing
Implement IWorkSchedulerDraggableData to enable horizontal movement, vertical movement, and per-item resizing. OnDragCompleted and OnResizeCompleted allow canceling the operation with Cancel.
public class DraggableWorkItem : WorkItem, IWorkSchedulerDraggableData
{
// Allows movement within the current row.
public bool AllowHorizontalMove { get; set; }
// Allows movement to another row.
public bool AllowVerticalMove { get; set; }
// Allows task resizing.
public bool AllowResize { get; set; }
}
Link tasks
Implement IWorkSchedulerLinkableData to draw links between tasks. TaskId identifies the task and Next contains the identifiers of subsequent tasks.
public class LinkedWorkItem : DraggableWorkItem, IWorkSchedulerLinkableData
{
// Unique identifier used by the link area.
public string TaskId { get; set; }
// Identifiers of tasks linked to this task.
public List<string> Next { get; set; } = new();
}
Agenda mode
DisplayMode="DisplayMode.Agenda" replaces project rows with a vertical hourly grid. Configure AgendaRowStep, AgendaHoursFrom, AgendaHoursTo, and the highlight bounds.
<LgWorkScheduler TItem="WorkItem"
Items="_items"
From="_from"
To="_to"
DisplayMode="DisplayMode.Agenda"
AgendaRowStep="30"
AgendaHoursFrom="TimeSpan.FromHours(8)"
AgendaHoursTo="TimeSpan.FromHours(18)"
RowField="@(item => item.RowId)" />
Control by reference
Add a reference to control scrolling or convert positions, dates, and durations.
<LgButton Text="#WksToday" OnClick="ScrollTodayAsync" />
<LgWorkScheduler @ref="_workScheduler"
TItem="WorkItem"
Items="_items"
From="_from"
To="_to"
RowField="@(item => item.RowId)" />
public partial class WorkSchedulerActionsPage : LgPage
{
// Reference used to call the component's public methods.
private LgWorkScheduler<WorkItem> _workScheduler;
// Centers the schedule on today's date.
private Task ScrollTodayAsync()
{
return _workScheduler.ScrollToTodayAsync();
}
}
Useful public methods: ScrollToAsync(double), ScrollToAsync(DateTime), ScrollToTodayAsync(), ScrollToEnd(), ScrollToStart(), GetTaskPosition(TItem), GetDatePosition(DateTime), GetTaskWidth(TItem), GetDurationWidth(DateTime, DateTime), GetDurationWidth(double), GetDateFromLeftPosition(double), GetRowPosition(), ExportAsync(...).
Child component LgWorkSchedulerDraggableItem
LgWorkSchedulerDraggableItem<TItem> declares an external item that the user can drop into an LgWorkScheduler<TItem>. WorkScheduler and Duration are required; Id is returned in OnDragCompletedEventArgs<TItem>.DroppedItemId.
<LgWorkScheduler @ref="_workScheduler"
TItem="WorkItem"
Items="_items"
From="_from"
To="_to"
RowField="@(item => item.RowId)"
OnDragCompleted="DropExternalItemAsync" />
@if (_workScheduler is not null)
{
<LgWorkSchedulerDraggableItem TItem="WorkItem"
WorkScheduler="_workScheduler"
Id="external-task-1"
Duration="TimeSpan.FromDays(2)"
Text="@("#WksExternalTask".Translate())"
CssClass="external-task" />
}
public partial class WorkSchedulerExternalDragPage : LgPage
{
// Adds a new task when an external item is dropped in the schedule.
private Task DropExternalItemAsync(OnDragCompletedEventArgs<WorkItem> args)
{
if (args.IsNew)
{
_items.Add(new WorkItem { RowId = Convert.ToInt32(args.RowId), From = args.NewStart, To = args.NewEnd, LabelKey = "#WksExternalTask" });
}
return Task.CompletedTask;
}
}
Properties of LgWorkSchedulerDraggableItem
| Name | Type | Default | Declared in | Description |
|---|---|---|---|---|
Id | string | null | LgWorkSchedulerDraggableItem<TItem> | Identifier returned on drop in DroppedItemId. |
Duration | TimeSpan? | null | LgWorkSchedulerDraggableItem<TItem> | Duration of the external item; required. |
Text | string | null | LgWorkSchedulerDraggableItem<TItem> | Text displayed in the droppable item. |
CssClass | string | null | LgWorkSchedulerDraggableItem<TItem> | CSS class added to the external item. |
WorkScheduler | LgWorkScheduler<TItem> | null | LgWorkSchedulerDraggableItem<TItem> | Instance of the target schedule; required. |
Properties
| Name | Type | Default | Declared in | Description |
|---|---|---|---|---|
OnSort | Func<IEnumerable<TItem>, IEnumerable<TItem>> | null | LgWorkScheduler<TItem> | Sorts the source before rendering. |
Timeline | TimelineMode | YearMonth | LgWorkScheduler<TItem> | Defines the horizontal granularity. |
DisplayMode | DisplayMode | Timeline | LgWorkScheduler<TItem> | Defines the main rendering. |
TimelineDisplayMode | TimelineDisplayMode | TwoRows | LgWorkScheduler<TItem> | Defines the number of timeline rows. |
GroupDisplayMode | GroupDisplayMode | Row | LgWorkScheduler<TItem> | Defines the rendering of groups. |
FocusTodayOnLoad | bool | false | LgWorkScheduler<TItem> | Automatically centers the schedule on today when loaded. |
AgendaRowStep | int | 30 | LgWorkScheduler<TItem> | Vertical step, in minutes, of agenda mode. |
AgendaHoursFrom | TimeSpan | 00:00:00 | LgWorkScheduler<TItem> | Start hour displayed in agenda mode. |
AgendaHoursTo | TimeSpan | 00:00:00 | LgWorkScheduler<TItem> | End hour displayed in agenda mode. |
AgendaHoursFromHighlight | TimeSpan | 00:00:00 | LgWorkScheduler<TItem> | Start of the hour range highlighted in agenda mode. |
AgendaHoursToHighlight | TimeSpan | 00:00:00 | LgWorkScheduler<TItem> | End of the hour range highlighted in agenda mode. |
AllowCollapseGroup | bool | true | LgWorkScheduler<TItem> | Allows collapsing and expanding groups. |
StateId | string | null | LgWorkScheduler<TItem> | Unique identifier used notably to restore scroll position. |
RestoreScrollPosition | bool | false | LgWorkScheduler<TItem> | Restores scroll position after a full reload if StateId is set. |
TimelineHeight | int | 50 | LgWorkScheduler<TItem> | Timeline height in pixels. |
ShowWeekend | bool | true | LgWorkScheduler<TItem> | Shows weekends in the timeline. |
From | DateTime? | null | LgWorkScheduler<TItem> | Start bound displayed; if absent, it is deduced from the data. |
To | DateTime? | null | LgWorkScheduler<TItem> | End bound displayed; if absent, it is deduced from the data. |
ZoomLevel | double | 4 | LgWorkScheduler<TItem> | Number of pixels representing one hour. |
ProjectListWidth | int | 200 | LgWorkScheduler<TItem> | Width of the project list in pixels. |
RowHeight | int | 50 | LgWorkScheduler<TItem> | Height of a row in pixels. |
PaddingRow | int | 7 | LgWorkScheduler<TItem> | Internal spacing of a row in pixels. |
Items | ICollection<TItem> | null | LgWorkScheduler<TItem> | Data to display. |
OnCustomDateIndicator | Func<DateTime, string> | null | LgWorkScheduler<TItem> | Formats the date displayed during movement or resizing. |
DragStepType | DragStepType | Free | LgWorkScheduler<TItem> | Defines the movement constraint. |
DragStepSize | TimeSpan? | null | LgWorkScheduler<TItem> | Custom step used if DragStepType is Manual. |
ShowMouseIndicator | bool | true | LgWorkScheduler<TItem> | Shows the mouse position indicator. |
ShowDragIndicator | bool | false | LgWorkScheduler<TItem> | Shows the indicator during movement or resizing. |
VirtualScrolling | bool | false | LgWorkScheduler<TItem> | Enables virtual scrolling for large volumes. |
ShowProjectResizing | bool | true | LgWorkScheduler<TItem> | Allows project list resizing. |
RowField | Func<TItem, object> | null | LgWorkScheduler<TItem> | Selects the row grouping key. |
GroupBy | IEnumerable<Func<TItem, object>> | null | LgWorkScheduler<TItem> | Defines grouping levels. |
OrderBy | IEnumerable<Func<TItem, object>> | null | LgWorkScheduler<TItem> | Defines row sort properties. |
GroupMargin | int | 30 | LgWorkScheduler<TItem> | Group indentation in pixels. |
DefaultGroupsState | GroupState | Close | LgWorkScheduler<TItem> | Initial state of groups. |
DefaultJalonCssClass | string | "wk-milestone-square" | LgWorkScheduler<TItem> | Default CSS class for milestones. |
JoinMilestone | bool | false | LgWorkScheduler<TItem> | Links milestones together on the same row. |
HourStep | int | 3 | LgWorkScheduler<TItem> | Hour step of TimelineMode.DayHour. |
DatesCustomHighlight | Dictionary<DateTime, string> | null | LgWorkScheduler<TItem> | Dates highlighted with a CSS class per date. |
ProjectHeader | RenderFragment | null | LgWorkScheduler<TItem> | Content of the project list header. |
ProjectItems | RenderFragment<TItem> | null | LgWorkScheduler<TItem> | Rendering of a row in the project list. |
ProjectItemsGroup | RenderFragment<GroupItem<TItem>> | null | LgWorkScheduler<TItem> | Rendering of a group in the project list. |
SchedulerItems | RenderFragment<TItem> | null | LgWorkScheduler<TItem> | Rendering of a task or milestone in the schedule area. |
SchedulerItemsGroup | RenderFragment<GroupItem<TItem>> | null | LgWorkScheduler<TItem> | Rendering of a group in the schedule area. |
AgendaHoursRender | RenderFragment<TimeSpan> | null | LgWorkScheduler<TItem> | Rendering of an hour mark in agenda mode. |
TimelineFirstLevel | RenderFragment<DateTime> | null | LgWorkScheduler<TItem> | Rendering of the first timeline level. |
TimelineSecondLevel | RenderFragment<DateTime> | null | LgWorkScheduler<TItem> | Rendering of the second timeline level. |
ChildContent | RenderFragment | null | LgWorkScheduler<TItem> | Child content; used only to declare named fragments. |
IgnoreFormTracking | bool | false | IFormTrackerComponent | Excludes the component from change tracking by an LgFormTracker. |
Events
| Name | Type | Description |
|---|---|---|
OnItemClick | EventCallback<TItem> | Triggered on a click on a task or milestone. |
OnEmptyClick | EventCallback<OnEmptyClickEventArgs> | Triggered on a click in an empty area; exposes RowId and Date. |
OnDragCompleted | EventCallback<OnDragCompletedEventArgs<TItem>> | Triggered at the end of a movement; exposes the item, target row, dates, and Cancel. |
OnResizeCompleted | EventCallback<OnResizeCompletedEventArgs<TItem>> | Triggered at the end of a resize; exposes the new dates and Cancel. |
Associated enumerations
TimelineMode
| Value | Default | Description |
|---|---|---|
YearMonth | Yes | Year at first level, month at second. |
MonthDay | No | Month at first level, days at second. |
DayAmPm | No | Day at first level, half-day at second. |
DayHour | No | Days at first level, hours at second. |
MonthWeek | No | Month at first level, week numbers at second. |
MonthWeekDay | No | Month, weeks, then days on three levels. |
WeekDay | No | Week numbers at first level, days at second. |
DisplayMode
| Value | Default | Description |
|---|---|---|
Timeline | Yes | Displays bars and milestones with the project list. |
Agenda | No | Displays an agenda grid with vertical hour axis. |
TimelineDisplayMode
| Value | Default | Description |
|---|---|---|
OneRow | No | Displays the timeline on one row. |
TwoRows | Yes | Displays the timeline on two rows. |
ThreeRows | No | Displays the timeline on three rows. |
GroupDisplayMode
| Value | Default | Description |
|---|---|---|
Row | Yes | Displays groups as rows. |
Column | No | Displays groups as columns. |
GroupState
| Value | Default | Description |
|---|---|---|
Open | No | Group open. |
Close | Yes | Group closed. |
DragStepType
| Value | Default | Description |
|---|---|---|
Free | Yes | No step imposed during movement. |
Hour | No | Movement constrained to the hour. |
Day | No | Movement constrained to the day. |
Manual | No | Movement constrained by DragStepSize. |
Accessibility
- Provide explicit labels in
ProjectItemsandSchedulerItems, as custom rendering replaces the default content. - Actions in fragments must use Lagoon components (
LgButton,LgIconwith appropriate role) and translated text. - Do not hide weekends if tasks can start or end on these days: this creates ambiguous temporal reading.
ShowMouseIndicatoris a visual aid; do not use it as the only business indication.
Related components
LgWorkSchedulerDraggableItem<TItem>: external item droppable into a schedule.LgFormTracker: tracks changes whenIgnoreFormTrackingisfalse.