
Syncfusion Blazor Kanban
- 230 installs
- 4 repo stars
- Updated July 28, 2026
- syncfusion/blazor-ui-components-skills
Use syncfusion-blazor-kanban for development tasks
About
syncfusion-blazor-kanban: A skill for development. This provides functionality for development workflows.
- syncfusion-blazor-kanban
Syncfusion Blazor Kanban by the numbers
- 230 all-time installs (skills.sh)
- +13 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #1,715 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/syncfusion/blazor-ui-components-skills --skill syncfusion-blazor-kanbanAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 230 |
|---|---|
| repo stars | ★ 4 |
| Last updated | July 28, 2026 |
| Repository | syncfusion/blazor-ui-components-skills ↗ |
What it does
Use syncfusion-blazor-kanban for development tasks
Files
Implementing Syncfusion Blazor Kanban Component
When to Use This Skill
Use this skill when:
- Building Kanban boards or workflow management UIs in Blazor
- Implementing task/card management with column-based workflows
- Adding swimlane grouping to organize cards by assignee or category
- Enabling drag-and-drop card movement between columns
- Configuring WIP (Work-In-Progress) validation limits
- Customizing card appearance with templates
- Binding Kanban to local or remote data sources
- Integrating Kanban with external components (Schedule, TreeView)
Quick Start
1. Install NuGet Packages
dotnet add package Syncfusion.Blazor.Kanban
dotnet add package Syncfusion.Blazor.Themes2. Register Service (Program.cs)
using Syncfusion.Blazor;
builder.Services.AddSyncfusionBlazor();3. Add Imports (_Imports.razor)
@using Syncfusion.Blazor
@using Syncfusion.Blazor.Kanban4. Add Stylesheet and Script (index.html or App.razor)
<link href="_content/Syncfusion.Blazor.Themes/bootstrap5.css" rel="stylesheet" />
<script src="_content/Syncfusion.Blazor.Core/scripts/syncfusion-blazor.min.js" type="text/javascript"></script>5. Basic Kanban with Cards
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks">
<KanbanColumns>
<KanbanColumn HeaderText="To Do" KeyField="@(new List<string>() {"Open"})"></KanbanColumn>
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() {"InProgress"})"></KanbanColumn>
<KanbanColumn HeaderText="Testing" KeyField="@(new List<string>() {"Testing"})"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() {"Close"})"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Title" ContentField="Summary"></KanbanCardSettings>
</SfKanban>
@code {
public class TasksModel
{
public string Id { get; set; }
public string Title { get; set; }
public string Status { get; set; }
public string Summary { get; set; }
public string Assignee { get; set; }
}
public List<TasksModel> Tasks = new List<TasksModel>()
{
new TasksModel { Id = "Task 1", Title = "BLAZ-29001", Status = "Open", Summary = "Analyze the new requirements gathered from the customer.", Assignee = "Nancy Davloio" },
new TasksModel { Id = "Task 2", Title = "BLAZ-29002", Status = "InProgress", Summary = "Improve application performance", Assignee = "Andrew Fuller" },
new TasksModel { Id = "Task 3", Title = "BLAZ-29003", Status = "Open", Summary = "Arrange a web meeting with the customer.", Assignee = "Janet Leverling" },
new TasksModel { Id = "Task 4", Title = "BLAZ-29004", Status = "Testing", Summary = "Fix the issues reported by the customer.", Assignee = "Janet Leverling" },
new TasksModel { Id = "Task 5", Title = "BLAZ-29005", Status = "Close", Summary = "Fix the issues reported in Safari browser.", Assignee = "Steven walker" },
};
}Navigation Guide
| Topic | Reference File |
|---|---|
| Getting started (WebAssembly/Server/Web App) | getting-started.md |
| Data binding (local, remote, ExpandoObject, Observable) | data-binding.md |
| Column configuration | columns.md |
| Card customization | cards.md |
| Drag and drop (internal & external) | drag-and-drop.md |
| Swimlane grouping | swimlane.md |
| Card editing dialog | dialog.md |
| Events reference | events.md |
| Card sorting | sort.md |
| Workflow restrictions | workflow.md |
| WIP validation (MinCount/MaxCount) | validation.md |
| Styling and CSS classes | style.md |
| Accessibility (WCAG, keyboard navigation) | accessibility.md |
| Localization and RTL | localization.md |
| Tooltips | tooltip.md |
| Responsive mode | responsive-mode.md |
| Height and width dimensions | dimensions.md |
Common Patterns
Kanban with Swimlane
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks">
<KanbanColumns>
<KanbanColumn HeaderText="To Do" KeyField="@(new List<string>() {"Open"})"></KanbanColumn>
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() {"InProgress"})"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() {"Close"})"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Title" ContentField="Summary"></KanbanCardSettings>
<KanbanSwimlaneSettings KeyField="Assignee"></KanbanSwimlaneSettings>
</SfKanban>Kanban with WIP Validation
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks">
<KanbanColumns>
<KanbanColumn HeaderText="Backlog" KeyField="@(new List<string>() {"Open"})" MinCount="2"></KanbanColumn>
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() {"InProgress"})" MaxCount="3"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() {"Close"})"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Title" ContentField="Summary"></KanbanCardSettings>
</SfKanban>Kanban with Index-Based Sorting
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks">
<KanbanColumns>
<KanbanColumn HeaderText="To Do" KeyField="@(new List<string>() {"Open"})"></KanbanColumn>
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() {"InProgress"})"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() {"Close"})"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Title" ContentField="Summary"></KanbanCardSettings>
<KanbanSortSettings SortBy="SortOrderBy.Index" Field="RankId"></KanbanSortSettings>
</SfKanban>Key Properties Reference
| Property | Component | Description |
|---|---|---|
KeyField | SfKanban | Maps the data field that determines which column a card belongs to |
DataSource | SfKanban | Binds local or remote data to the Kanban |
AllowDragAndDrop | SfKanban | Enables/disables drag-and-drop (default: true) |
EnableTooltip | SfKanban | Shows card details on hover |
EnableRtl | SfKanban | Enables right-to-left layout |
HeaderField | KanbanCardSettings | Maps the unique ID field for card headers |
ContentField | KanbanCardSettings | Maps the field shown in card body |
KeyField | KanbanColumn | One or more status values that map cards to this column |
AllowToggle | KanbanColumn | Allows column expand/collapse |
MinCount | KanbanColumn | Minimum card count for WIP validation |
MaxCount | KanbanColumn | Maximum card count for WIP validation |
TransitionColumns | KanbanColumn | Restricts cards to only drop into specified columns |
AllowDrop | KanbanColumn | Prevents cards from being dropped into a column |
AllowDrag | KanbanColumn | Prevents cards from being dragged from a column |
KeyField | KanbanSwimlaneSettings | Groups cards into swimlane rows by this field |
SortBy | KanbanSortSettings | Sorting mode: DataSourceOrder, Index, or Custom |
Accessibility in Blazor Kanban Component
The Blazor Kanban component follows the WAI-ARIA specification and WCAG 2.2 standards, providing full keyboard navigation and screen reader support.
Table of Contents
WCAG Compliance
The Kanban component conforms to WCAG 2.2 AA level accessibility standards.
| Criteria | Description |
|---|---|
| 1.1.1 Non-text content | All controls have accessible labels |
| 1.3.1 Info and relationships | Semantic HTML structure and ARIA roles |
| 1.3.2 Meaningful sequence | Logical reading/focus order |
| 2.1.1 Keyboard | Full keyboard navigation support |
| 2.1.2 No keyboard trap | Focus can always move away |
| 3.2.2 On input | No unexpected context changes |
| 4.1.2 Name, Role, Value | All UI components have proper ARIA attributes |
WAI-ARIA Attributes
| Element | Attribute | Description |
|---|---|---|
| Kanban element | role="main" | Root role for the board |
| Column header | role="columnheader" | Identifies column header cells |
| Column header | aria-label | Accessible label with column name |
| Column toggle | role="button" | Toggle collapse/expand |
| Column toggle | aria-expanded | State of column expansion |
| Card | role="listitem" | Each card as a list item |
| Card | aria-label | Card header value |
| Card | aria-selected | Whether card is selected |
| Card | aria-grabbed | Whether card is being dragged |
| Card container | role="list" | Cards container |
| Swimlane | role="rowgroup" | Swimlane row |
| Swimlane header | role="row" | Swimlane header row |
| Swimlane toggle | aria-expanded | State of swimlane expansion |
| Dialog | role="dialog" | Card editing dialog |
| Dialog | aria-modal | Marks dialog as modal |
| Dialog | aria-labelledby | Dialog title reference |
Keyboard Navigation
Card Navigation
| Key | Description |
|---|---|
Home | Focus the first card in the column |
End | Focus the last card in the column |
Arrow Up | Move focus to the card above |
Arrow Down | Move focus to the card below |
Arrow Left | Move focus to the card in the previous column |
Arrow Right | Move focus to the card in the next column |
Enter | Open the card editing dialog |
Ctrl + Enter | Select/deselect the focused card |
Escape | Deselect all cards / close dialog |
Delete | Delete the focused card |
Ctrl + X | Cut the selected card(s) |
Ctrl + C | Copy the selected card(s) |
Ctrl + V | Paste card(s) into the focused column |
Space | Select/deselect the focused card |
Column Navigation
| Key | Description |
|---|---|
Tab | Move focus to the next column or interactive element |
Shift + Tab | Move focus to the previous column or element |
Ctrl + Arrow Left | Focus previous column header |
Ctrl + Arrow Right | Focus next column header |
Swimlane Navigation
| Key | Description |
|---|---|
Ctrl + Arrow Up | Move to the swimlane row above |
Ctrl + Arrow Down | Move to the swimlane row below |
Enter on swimlane | Toggle swimlane expand/collapse |
Enabling Keyboard Interaction
Keyboard interaction is enabled by default. Disable it with AllowKeyboard="false":
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks" AllowKeyboard="true">
<KanbanColumns>
<KanbanColumn HeaderText="Backlog" KeyField="@(new List<string>() {"Open"})"></KanbanColumn>
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() {"InProgress"})"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() {"Close"})"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Id" ContentField="Summary"></KanbanCardSettings>
</SfKanban>TheAllowKeyboardproperty defaults totrue. Set it tofalseonly if keyboard accessibility is explicitly not needed.
Working with Cards in Blazor Kanban Component
Cards are the main elements of the Kanban board, representing task information with a header and content.
Table of Contents
Header and Content
Map the HeaderField and ContentField properties in KanbanCardSettings:
<KanbanCardSettings HeaderField="Id" ContentField="Summary"></KanbanCardSettings>Disable the header display with ShowHeader="false":
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks">
<KanbanColumns>
<KanbanColumn HeaderText="Backlog" KeyField="@(new List<string>() {"Open"})"></KanbanColumn>
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() {"InProgress"})"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() {"Close"})"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings ShowHeader="false" HeaderField="Id" ContentField="Summary"></KanbanCardSettings>
</SfKanban>HeaderField must map to a unique value in the data source to avoid duplicate card data.Tags
Display tag text with background color using the TagsField property. Multiple tags are comma-separated in the data source:
<KanbanCardSettings HeaderField="Id" ContentField="Summary" TagsField="CardTags"></KanbanCardSettings>// Model with tags
public class TasksModel
{
public string Id { get; set; }
public string Status { get; set; }
public string Summary { get; set; }
public List<string> CardTags { get; set; }
}
// Sample data
new TasksModel { Id = "Task 1", Status = "Open", Summary = "Analyze requirements.", CardTags = new List<string>() { "Analyze", "Customer" } }Customizing Left Border Color
Map a color field to the GrabberField to set a custom left border color per card:
<KanbanCardSettings HeaderField="Id" ContentField="Summary" GrabberField="Color"></KanbanCardSettings>new TasksModel { Id = "Task 1", Status = "Open", Summary = "Analyze requirements.", Color = "#8b447a" }Default card border left width is 3px.Rendering Custom Footer Elements
Map CSS class names to the FooterCssField to render custom elements in the card footer:
<KanbanCardSettings HeaderField="Id" ContentField="Summary" FooterCssField="ClassName"></KanbanCardSettings>new TasksModel { Id = "Task 1", Status = "Open", Summary = "Analyze requirements.",
ClassName = new List<string>() { "e-story", "e-low", "e-nancy" } }Add corresponding CSS to display custom elements (icons, images) inside .e-card-footer.
Customizing Card Layout with Templates
Use Template inside KanbanCardSettings to define a fully custom card layout:
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks">
<KanbanColumns>
<KanbanColumn HeaderText="Backlog" KeyField="@(new List<string>() {"Open"})"></KanbanColumn>
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() {"InProgress"})"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() {"Close"})"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Id" ContentField="Summary">
<Template>
@{
TasksModel data = (TasksModel)context;
<div class="e-card-content">
<table class="card-template-wrap">
<tbody>
<tr>
<td class="CardHeader">Id:</td>
<td>@data.Id</td>
</tr>
<tr>
<td class="CardHeader">Type:</td>
<td>@data.Type</td>
</tr>
<tr>
<td class="CardHeader">Priority:</td>
<td>@data.Priority</td>
</tr>
<tr>
<td class="CardHeader">Summary:</td>
<td>@data.Summary</td>
</tr>
</tbody>
</table>
</div>
}
</Template>
</KanbanCardSettings>
</SfKanban>
<style>
.e-kanban .card-template-wrap .CardHeader { font-weight: 500; }
</style>
@code {
public class TasksModel
{
public string Id { get; set; }
public string Status { get; set; }
public string Summary { get; set; }
public string Type { get; set; }
public string Priority { get; set; }
public string Assignee { get; set; }
}
public List<TasksModel> Tasks = new List<TasksModel>()
{
new TasksModel { Id = "Task 1", Status = "Open", Summary = "Analyze the new requirements gathered from the customer.", Type = "Story", Priority = "Low", Assignee = "Nancy Davloio" },
new TasksModel { Id = "Task 2", Status = "InProgress", Summary = "Improve application performance", Type = "Improvement", Priority = "Normal", Assignee = "Andrew Fuller" },
new TasksModel { Id = "Task 3", Status = "Open", Summary = "Arrange a web meeting with the customer.", Type = "Others", Priority = "Critical", Assignee = "Janet Leverling" },
new TasksModel { Id = "Task 4", Status = "InProgress", Summary = "Fix the issues reported in the IE browser.", Type = "Bug", Priority = "Release Breaker", Assignee = "Janet Leverling" },
new TasksModel { Id = "Task 5", Status = "Review", Summary = "Fix the issues reported by the customer.", Type = "Bug", Priority = "Low", Assignee = "Steven walker" },
};
}Selection
Control card selection behavior with SelectionType:
| Value | Description |
|---|---|
None | No cards can be selected |
Single | Only one card at a time (default) |
Multiple | Multiple cards can be selected |
<KanbanCardSettings HeaderField="Id" ContentField="Summary" SelectionType="SelectionType.Multiple"></KanbanCardSettings>- Multi-select randomly:
Ctrl + click - Multi-select range:
Shift + click
KanbanCardSettings Properties
| Property | Type | Description |
|---|---|---|
HeaderField | string | Unique field for card header (must be unique in data source) |
ContentField | string | Field displayed in card body |
ShowHeader | bool | Show/hide card header (default: true) |
TagsField | string | Field containing tag values (comma-separated or List) |
GrabberField | string | Field providing left border color value |
FooterCssField | string | Field containing CSS class names for card footer |
SelectionType | SelectionType | Card selection mode: None, Single, Multiple |
Columns in Blazor Kanban Component
Kanban columns represent each stage of the workflow process. Column definitions serve as the schema for the Kanban board's DataSource.
Single-Key Mapping
Map a single data value to a column using the KeyField property:
@using Syncfusion.Blazor.Kanban
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks">
<KanbanColumns>
<KanbanColumn HeaderText="Backlog" KeyField="@(new List<string>() {"Open"})"></KanbanColumn>
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() {"InProgress"})"></KanbanColumn>
<KanbanColumn HeaderText="Testing" KeyField="@(new List<string>() {"Testing"})"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() {"Close"})"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Id" ContentField="Summary"></KanbanCardSettings>
</SfKanban>
@code {
public class TasksModel
{
public string Id { get; set; }
public string Title { get; set; }
public string Status { get; set; }
public string Summary { get; set; }
public string Assignee { get; set; }
}
public List<TasksModel> Tasks = new List<TasksModel>()
{
new TasksModel { Id = "Task 1", Title = "BLAZ-29001", Status = "Open", Summary = "Analyze the new requirements gathered from the customer.", Assignee = "Nancy Davloio" },
new TasksModel { Id = "Task 2", Title = "BLAZ-29002", Status = "InProgress", Summary = "Improve application performance", Assignee = "Andrew Fuller" },
new TasksModel { Id = "Task 3", Title = "BLAZ-29003", Status = "Open", Summary = "Arrange a web meeting with the customer to get new requirements.", Assignee = "Janet Leverling" },
new TasksModel { Id = "Task 4", Title = "BLAZ-29004", Status = "InProgress", Summary = "Fix the issues reported in the IE browser.", Assignee = "Janet Leverling" },
new TasksModel { Id = "Task 5", Title = "BLAZ-29005", Status = "Review", Summary = "Fix the issues reported by the customer.", Assignee = "Steven walker" },
};
}The KeyField property is required to render columns on the Kanban board.Multi-Key Mapping
Render a single column with multiple key values:
<KanbanColumn HeaderText="Backlog" KeyField="@(new List<string>() {"Open", "Validate"})"></KanbanColumn>Toggle Columns
Enable expand/collapse on columns with AllowToggle:
<SfKanban KeyField="Status" DataSource="Tasks">
<KanbanColumns>
<KanbanColumn HeaderText="Backlog" KeyField="@(new List<string>() {"Open"})" AllowToggle="true"></KanbanColumn>
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() {"InProgress"})" AllowToggle="true"></KanbanColumn>
<KanbanColumn HeaderText="Testing" KeyField="@(new List<string>() {"Testing"})" AllowToggle="true"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() {"Close"})" AllowToggle="true"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Id" ContentField="Summary"></KanbanCardSettings>
</SfKanban>By default, collapsed column width is 50px.Initially Collapsed Column
Use IsExpanded="false" to render a column collapsed on load. Requires AllowToggle="true":
<KanbanColumn HeaderText="Backlog" KeyField="@(new List<string>() {"Open"})" AllowToggle="true" IsExpanded="false"></KanbanColumn>
<KanbanColumn HeaderText="Testing" KeyField="@(new List<string>() {"Testing"})" AllowToggle="true" IsExpanded="false"></KanbanColumn>Header Template
Customize column headers using a Template:
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks">
<KanbanColumns>
<KanbanColumn HeaderText="Backlog" KeyField="@(new List<string>() {"Open"})">
<Template>
@{
KanbanColumn column = (KanbanColumn)context;
<div class="header-template-wrap">
<div class="header-icon e-icons @column.KeyField[0]"></div>
<div class="header-text">@column.HeaderText</div>
</div>
}
</Template>
</KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Id" ContentField="Summary"></KanbanCardSettings>
</SfKanban>Stacked Headers
Group related columns under a common category:
<SfKanban KeyField="Status" DataSource="Tasks">
<KanbanColumns>
<KanbanColumn HeaderText="To Do" KeyField="@(new List<string>() {"Open"})"></KanbanColumn>
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() {"InProgress"})"></KanbanColumn>
<KanbanColumn HeaderText="Testing" KeyField="@(new List<string>() {"Testing"})"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() {"Close"})"></KanbanColumn>
</KanbanColumns>
<KanbanStackedHeaders>
<KanbanStackedHeader Text="To Do" KeyFields="@(new List<string>() {"Open"})"></KanbanStackedHeader>
<KanbanStackedHeader Text="Development Phase" KeyFields="@(new List<string>() {"InProgress", "Testing"})"></KanbanStackedHeader>
<KanbanStackedHeader Text="Done" KeyFields="@(new List<string>() {"Close"})"></KanbanStackedHeader>
</KanbanStackedHeaders>
<KanbanCardSettings HeaderField="Id" ContentField="Summary"></KanbanCardSettings>
</SfKanban>Column Properties Reference
| Property | Type | Description |
|---|---|---|
HeaderText | string | Display text for the column header |
KeyField | List<string> | One or more status values mapped to this column |
AllowToggle | bool | Enables expand/collapse toggle icon |
IsExpanded | bool | Controls initial expanded/collapsed state (requires AllowToggle) |
AllowAdding | bool | Shows an add card button in the column |
ShowItemCount | bool | Shows total card count in the column header |
MinCount | int | Minimum WIP limit (see validation.md) |
MaxCount | int | Maximum WIP limit (see validation.md) |
TransitionColumns | List<string> | Restricts cards to only move to specified columns |
AllowDrop | bool | Prevents cards from being dropped into this column |
AllowDrag | bool | Prevents cards from being dragged from this column |
Data Binding in Blazor Kanban Component
The Kanban uses SfDataManager, which supports both RESTful JSON data services and IEnumerable binding.
Table of Contents
- Local Data Binding
- ExpandoObject Binding
- DynamicObject Binding
- Observable Collection
- Remote Data Binding
- Complex Data Binding
Local Data Binding
Assign an IEnumerable object to the DataSource property:
@using Syncfusion.Blazor.Kanban
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="@Tasks">
<KanbanColumns>
<KanbanColumn HeaderText="To Do" KeyField="@(new List<string>() {"Open"})"></KanbanColumn>
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() {"InProgress"})"></KanbanColumn>
<KanbanColumn HeaderText="Testing" KeyField="@(new List<string>() {"Testing"})"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() {"Close"})"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Id" ContentField="Summary"></KanbanCardSettings>
</SfKanban>
@code {
public class TasksModel
{
public int Id { get; set; }
public string Status { get; set; }
public string Summary { get; set; }
}
public List<TasksModel> Tasks { get; set; }
protected override void OnInitialized()
{
Tasks = Enumerable.Range(1, 10).Select(x => new TasksModel()
{
Id = 1000 + x,
Status = (new string[] { "Open", "InProgress", "Testing", "Close" })[new Random().Next(4)],
Summary = (new string[] { "Analyze SQL server connection.", "Fix issues in Safari browser.", "Improve application performance", "Analyze grid control." })[new Random().Next(4)],
}).ToList();
}
}By default,SfDataManagerusesBlazorAdaptorfor list data binding.
Binding with ExpandoObject
Bind data as a list of ExpandoObject when the model type is unknown at compile time:
@using Syncfusion.Blazor.Kanban
@using System.Dynamic
<SfKanban KeyField="Status" DataSource="@Tasks">
<KanbanColumns>
@foreach (ColumnModel item in columnData)
{
<KanbanColumn HeaderText="@item.HeaderText" KeyField="@item.KeyField" AllowAdding="true"></KanbanColumn>
}
</KanbanColumns>
<KanbanCardSettings HeaderField="Id" ContentField="Summary"></KanbanCardSettings>
</SfKanban>
@code {
public List<ExpandoObject> Tasks { get; set; } = new List<ExpandoObject>();
private List<ColumnModel> columnData = new List<ColumnModel>() {
new ColumnModel(){ HeaderText= "To Do", KeyField= new List<string>() { "Open" } },
new ColumnModel(){ HeaderText= "In Progress", KeyField= new List<string>() { "In Progress" } },
new ColumnModel(){ HeaderText= "Testing", KeyField= new List<string>() { "Testing" } },
new ColumnModel(){ HeaderText= "Done", KeyField=new List<string>() { "Close" } }
};
protected override void OnInitialized()
{
Tasks = Enumerable.Range(1, 20).Select((x) =>
{
dynamic d = new ExpandoObject();
d.Id = "Task 1000" + x;
d.Status = (new string[] { "Open", "In Progress", "Testing", "Close" })[new Random().Next(4)];
d.Summary = (new string[] { "Analyze the new requirements.", "Improve application performance", "Fix the issues reported in the IE browser.", "Validate new requirements" })[new Random().Next(4)];
d.Assignee = (new string[] { "Nancy Davloio", "Andrew Fuller", "Janet Leverling", "Steven walker" })[new Random().Next(4)];
return d;
}).Cast<ExpandoObject>().ToList<ExpandoObject>();
}
}Binding with DynamicObject
Override GetDynamicMemberNames to perform data operations and editing:
@using Syncfusion.Blazor.Kanban
@using System.Dynamic
<SfKanban KeyField="Status" DataSource="@Tasks">
<KanbanColumns>
@foreach (ColumnModel item in columnData)
{
<KanbanColumn HeaderText="@item.HeaderText" KeyField="@item.KeyField" AllowAdding="true"></KanbanColumn>
}
</KanbanColumns>
<KanbanCardSettings HeaderField="Id" ContentField="Summary"></KanbanCardSettings>
</SfKanban>
@code {
private List<ColumnModel> columnData = new List<ColumnModel>() {
new ColumnModel(){ HeaderText= "To Do", KeyField= new List<string>() { "Open" } },
new ColumnModel(){ HeaderText= "In Progress", KeyField= new List<string>() { "In Progress" } },
new ColumnModel(){ HeaderText= "Testing", KeyField= new List<string>() { "Testing" } },
new ColumnModel(){ HeaderText= "Done", KeyField=new List<string>() { "Close" } }
};
public List<DynamicDictionary> Tasks = new List<DynamicDictionary>() { };
protected override void OnInitialized()
{
Tasks = Enumerable.Range(1, 20).Select((x) =>
{
dynamic d = new DynamicDictionary();
d.Id = "Task 1000" + x;
d.Status = (new string[] { "Open", "In Progress", "Testing", "Close" })[new Random().Next(4)];
d.Summary = (new string[] { "Analyze the new requirements.", "Improve application performance", "Fix the issues reported in the IE browser." })[new Random().Next(3)];
return d;
}).Cast<DynamicDictionary>().ToList<DynamicDictionary>();
}
public class DynamicDictionary : System.Dynamic.DynamicObject
{
Dictionary<string, object> dictionary = new Dictionary<string, object>();
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
string name = binder.Name;
return dictionary.TryGetValue(name, out result);
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
dictionary[binder.Name] = value;
return true;
}
public override System.Collections.Generic.IEnumerable<string> GetDynamicMemberNames()
{
return this.dictionary?.Keys;
}
}
}Binding with Observable Collection
Use ObservableCollection for real-time UI updates when items are added, removed, or moved:
@using Syncfusion.Blazor.Kanban
@using System.Collections.ObjectModel;
@using System.ComponentModel;
<SfKanban KeyField="Status" DataSource="@ObservableData">
<KanbanColumns>
@foreach (ColumnModel item in columnData)
{
<KanbanColumn HeaderText="@item.HeaderText" KeyField="@item.KeyField" AllowAdding="true" />
}
</KanbanColumns>
<KanbanCardSettings HeaderField="Id" ContentField="Summary" />
</SfKanban>
@code {
private List<ColumnModel> columnData = new List<ColumnModel>() {
new ColumnModel(){ HeaderText= "To Do", KeyField= new List<string>() { "Open" } },
new ColumnModel(){ HeaderText= "In Progress", KeyField= new List<string>() { "In Progress" } },
new ColumnModel(){ HeaderText= "Testing", KeyField= new List<string>() { "Testing" } },
new ColumnModel(){ HeaderText= "Done", KeyField=new List<string>() { "Close" } }
};
public ObservableCollection<ObservableDatas> ObservableData { get; set; }
protected override void OnInitialized()
{
var tasks = Enumerable.Range(1, 20).Select(x => new ObservableDatas()
{
Id = "Task 1000" + x,
Status = (new string[] { "Open", "In Progress", "Testing", "Close" })[new Random().Next(4)],
Summary = "Task summary " + x,
Assignee = (new string[] { "Nancy Davloio", "Andrew Fuller", "Janet Leverling" })[new Random().Next(3)],
}).ToList();
ObservableData = new ObservableCollection<ObservableDatas>(tasks);
}
public class ObservableDatas : INotifyPropertyChanged
{
public string Id { get; set; }
private string status { get; set; }
public string Status
{
get { return status; }
set
{
this.status = value;
NotifyPropertyChanged("Status");
}
}
public string Summary { get; set; }
public string Assignee { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}Remote Data Binding
OData Service
@using Syncfusion.Blazor.Data
@using Syncfusion.Blazor.Kanban
<SfKanban TValue="Order" KeyField="ShipCountry" AllowDragAndDrop="false">
<SfDataManager Url="https://js.syncfusion.com/ejServices/Wcf/Northwind.svc/Orders" Adaptor="@Syncfusion.Blazor.Adaptors.ODataAdaptor"></SfDataManager>
<KanbanColumns>
<KanbanColumn HeaderText="Denmark" KeyField="@(new List<string>() { "Denmark" })"></KanbanColumn>
<KanbanColumn HeaderText="Brazil" KeyField="@(new List<string>() { "Brazil" })"></KanbanColumn>
<KanbanColumn HeaderText="Germany" KeyField="@(new List<string>() { "Germany" })"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="OrderID" ContentField="ShipName"></KanbanCardSettings>
<KanbanEvents TValue="Order" DialogOpen="@((args)=> { args.Cancel = true; })"></KanbanEvents>
</SfKanban>
@code {
public class Order
{
public int? OrderID { get; set; }
public string ShipName { get; set; }
public string ShipCountry { get; set; }
}
}Web API
@using Syncfusion.Blazor.Data
@using Syncfusion.Blazor.Kanban
<SfKanban TValue="TasksModel" KeyField="Status" AllowDragAndDrop="false">
<SfDataManager Url="https://blazor.syncfusion.com/services/production/api/Kanban" Adaptor="@Syncfusion.Blazor.Adaptors.WebApiAdaptor"></SfDataManager>
<KanbanColumns>
<KanbanColumn HeaderText="To Do" KeyField="@(new List<string>() { "Open" })"></KanbanColumn>
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() { "InProgress" })"></KanbanColumn>
<KanbanColumn HeaderText="Testing" KeyField="@(new List<string>() { "Testing" })"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() { "Close" })"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Id" ContentField="Summary"></KanbanCardSettings>
<KanbanEvents TValue="TasksModel" DialogOpen="@((args) => { args.Cancel = true; })"></KanbanEvents>
</SfKanban>
@code {
public class TasksModel
{
public int Id { get; set; }
public string Status { get; set; }
public string Assignee { get; set; }
public string Summary { get; set; }
}
}Sending Additional Parameters
<SfKanban TValue="TasksModel" KeyField="Status" AllowDragAndDrop="false" Query=@KanbanQuery>
<SfDataManager Url="https://blazor.syncfusion.com/services/production/api/Kanban" Adaptor="@Syncfusion.Blazor.Adaptors.WebApiAdaptor"></SfDataManager>
...
</SfKanban>
@code {
public Query KanbanQuery { get; set; }
protected override void OnInitialized()
{
KanbanQuery = new Query().AddParams("BlazorKanban", "true");
}
}Complex Data Binding
Map nested properties to Kanban fields using dot notation:
<SfKanban TValue="SwimlaneTasksModel" KeyField="Status.KeyField" DataSource="KanbanSwimlaneTasks">
<KanbanColumns>
<KanbanColumn HeaderText="Backlog" KeyField="@(new List<string>() {"Open"})" AllowAdding="true" />
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() {"InProgress"})" />
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() {"Close"})" />
</KanbanColumns>
<KanbanCardSettings HeaderField="Id.HeaderId" ContentField="Summary.Content" />
<KanbanSwimlaneSettings KeyField="AssigneeName.Name" AllowDragAndDrop="true" />
</SfKanban>
@code {
public class SwimlaneTasksModel
{
public HeaderModel Id { get; set; }
public StatusModel Status { get; set; }
public ContentModel Summary { get; set; }
public SwimlaneAssignee AssigneeName { get; set; }
}
public class StatusModel { public string KeyField { get; set; } }
public class HeaderModel { public int HeaderId { get; set; } }
public class ContentModel { public string Content { get; set; } }
public class SwimlaneAssignee { public string Name { get; set; } }
}Dialog in Blazor Kanban Component
The Kanban component provides a built-in dialog for adding, editing, and deleting cards by double-clicking a card or an empty cell.
Table of Contents
- Default Dialog Behavior
- Custom Fields in Dialog
- Dialog Template
- Preventing Dialog from Opening
- Server-Side CRUD Operations
Dialog
The dialog opens automatically on double-click. Use KanbanDialogSettings to configure:
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks">
<KanbanColumns>
<KanbanColumn HeaderText="Backlog" KeyField="@(new List<string>() {"Open"})"></KanbanColumn>
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() {"InProgress"})"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() {"Close"})"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Id" ContentField="Summary"></KanbanCardSettings>
<KanbanDialogSettings>
<KanbanDialogSettingsFields>
<KanbanDialogSettingsField Text="ID" Key="Id" Type="DialogFieldType.TextBox"></KanbanDialogSettingsField>
<KanbanDialogSettingsField Text="Status" Key="Status" Type="DialogFieldType.DropDown"></KanbanDialogSettingsField>
<KanbanDialogSettingsField Text="Assignee" Key="Assignee" Type="DialogFieldType.DropDown"></KanbanDialogSettingsField>
<KanbanDialogSettingsField Text="Priority" Key="Priority" Type="DialogFieldType.DropDown"></KanbanDialogSettingsField>
<KanbanDialogSettingsField Text="Summary" Key="Summary" Type="DialogFieldType.TextArea"></KanbanDialogSettingsField>
</KanbanDialogSettingsFields>
</KanbanDialogSettings>
</SfKanban>Custom Fields
Control which fields appear in the dialog and their input types:
DialogFieldType | Description |
|---|---|
TextBox | Single-line text input field |
DropDown | Dropdown list |
Numeric | Numeric input |
TextArea | Multi-line text area |
<KanbanDialogSettingsFields>
<KanbanDialogSettingsField Text="Title" Key="Title" Type="DialogFieldType.TextBox"></KanbanDialogSettingsField>
<KanbanDialogSettingsField Text="Status" Key="Status" Type="DialogFieldType.DropDown"></KanbanDialogSettingsField>
<KanbanDialogSettingsField Text="Story Points" Key="StoryPoints" Type="DialogFieldType.Numeric"></KanbanDialogSettingsField>
<KanbanDialogSettingsField Text="Description" Key="Summary" Type="DialogFieldType.TextArea"></KanbanDialogSettingsField>
</KanbanDialogSettingsFields>Dialog Template
Fully replace the dialog content with a custom template using Template inside KanbanDialogSettings:
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks">
<KanbanColumns>
<KanbanColumn HeaderText="Backlog" KeyField="@(new List<string>() {"Open"})"></KanbanColumn>
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() {"InProgress"})"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() {"Close"})"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Id" ContentField="Summary"></KanbanCardSettings>
<KanbanDialogSettings>
<Template>
@{
TasksModel data = (TasksModel)context;
<table>
<tbody>
<tr>
<td class="e-label">ID</td>
<td><input class="e-field e-input" name="Id" value="@data.Id" /></td>
</tr>
<tr>
<td class="e-label">Status</td>
<td>
<SfDropDownList TValue="string" TItem="DropDownModel"
DataSource="StatusData" Value="@data.Status">
<DropDownListFieldSettings Text="Value" Value="Value"></DropDownListFieldSettings>
</SfDropDownList>
</td>
</tr>
<tr>
<td class="e-label">Summary</td>
<td><textarea class="e-field e-input" name="Summary">@data.Summary</textarea></td>
</tr>
</tbody>
</table>
}
</Template>
</KanbanDialogSettings>
</SfKanban>
@code {
public class DropDownModel { public string Value { get; set; } }
public List<DropDownModel> StatusData = new List<DropDownModel>
{
new DropDownModel { Value = "Open" },
new DropDownModel { Value = "InProgress" },
new DropDownModel { Value = "Close" }
};
}Prevent Dialog
Use the DialogOpen event and set args.Cancel = true to prevent the dialog from opening:
<KanbanEvents TValue="TasksModel" DialogOpen="DialogOpenHandler"></KanbanEvents>
@code {
private void DialogOpenHandler(DialogOpenEventArgs<TasksModel> args)
{
args.Cancel = true; // Prevent dialog from opening
}
}Server-Side CRUD
When using a remote data source (UrlAdaptor), CRUD operations are handled by the server. The Kanban sends requests automatically on drag/drop and dialog save/delete:
<SfKanban TValue="TasksModel" KeyField="Status">
<KanbanDataManager Url="/api/Kanban" AdaptorType="Adaptors.UrlAdaptor" CrossDomain="true"></KanbanDataManager>
<KanbanColumns>
<KanbanColumn HeaderText="Backlog" KeyField="@(new List<string>() {"Open"})"></KanbanColumn>
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() {"InProgress"})"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() {"Close"})"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Id" ContentField="Summary"></KanbanCardSettings>
<KanbanDialogSettings>
<KanbanDialogSettingsFields>
<KanbanDialogSettingsField Text="ID" Key="Id" Type="DialogFieldType.TextBox"></KanbanDialogSettingsField>
<KanbanDialogSettingsField Text="Status" Key="Status" Type="DialogFieldType.DropDown"></KanbanDialogSettingsField>
<KanbanDialogSettingsField Text="Summary" Key="Summary" Type="DialogFieldType.TextArea"></KanbanDialogSettingsField>
</KanbanDialogSettingsFields>
</KanbanDialogSettings>
</SfKanban>Server controller must handle:
POST /api/Kanban— GetCards (initial load)POST /api/Kanban/Insert— Create cardPOST /api/Kanban/Update— Update cardPOST /api/Kanban/Delete— Delete card
Dialog Events
| Event | Description |
|---|---|
DialogOpen | Fires before the dialog opens; set args.Cancel = true to prevent |
DialogClose | Fires when the dialog closes |
Dimensions in Blazor Kanban Component
Control the width and height of the Kanban component using the Width and Height properties.
Table of Contents
Auto Dimensions
By default, both Width and Height are set to "auto", which makes the Kanban fit its content and parent container:
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks"
Width="auto" Height="auto">
<KanbanColumns>
<KanbanColumn HeaderText="Backlog" KeyField="@(new List<string>() {"Open"})"></KanbanColumn>
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() {"InProgress"})"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() {"Close"})"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Id" ContentField="Summary"></KanbanCardSettings>
</SfKanban>Width="auto": Expands to fit the parent container widthHeight="auto": Expands to fit the total card content (no vertical scroll)
Pixel Dimensions
Set fixed pixel dimensions for a fixed-size board:
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks"
Width="650px" Height="550px">
<KanbanColumns>
<KanbanColumn HeaderText="Backlog" KeyField="@(new List<string>() {"Open"})"></KanbanColumn>
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() {"InProgress"})"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() {"Close"})"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Id" ContentField="Summary"></KanbanCardSettings>
</SfKanban>
@code {
public class TasksModel
{
public string Id { get; set; }
public string Status { get; set; }
public string Summary { get; set; }
}
public List<TasksModel> Tasks = new List<TasksModel>()
{
new TasksModel { Id = "Task 1", Status = "Open", Summary = "Analyze the new requirements gathered from the customer." },
new TasksModel { Id = "Task 2", Status = "InProgress", Summary = "Improve application performance." },
new TasksModel { Id = "Task 3", Status = "Open", Summary = "Arrange a web meeting with the customer." },
new TasksModel { Id = "Task 4", Status = "InProgress", Summary = "Fix the issues reported in the IE browser." },
new TasksModel { Id = "Task 5", Status = "Close", Summary = "Validate new requirements." },
};
}When Height is set to a fixed pixel value, the content area scrolls vertically when cards exceed the visible area.Percentage Dimensions
Set dimensions as a percentage of the parent container:
<div style="width: 100%; height: 600px;">
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks"
Width="100%" Height="100%">
<KanbanColumns>
<KanbanColumn HeaderText="Backlog" KeyField="@(new List<string>() {"Open"})"></KanbanColumn>
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() {"InProgress"})"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() {"Close"})"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Id" ContentField="Summary"></KanbanCardSettings>
</SfKanban>
</div>When using percentageHeight, ensure the parent container has a defined height. Without a parent height,100%may resolve to0.
Dimensions Properties Reference
| Property | Type | Default | Description |
|---|---|---|---|
Width | string | "auto" | Width of the Kanban board (px, %, or auto) |
Height | string | "auto" | Height of the Kanban board (px, %, or auto) |
Dimension Value Examples
| Value | Effect |
|---|---|
"auto" | Fits content/parent container |
"650px" | Fixed 650-pixel width or height |
"100%" | Fills 100% of parent container dimension |
"80vh" | Sets height to 80% of the viewport height |
Frozen Swimlane Rows with Fixed Height
When using EnableFrozenRows on swimlanes, a fixed height is required for the scroll behavior to work:
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks" Height="500px">
<KanbanColumns>
<KanbanColumn HeaderText="Backlog" KeyField="@(new List<string>() {"Open"})"></KanbanColumn>
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() {"InProgress"})"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() {"Close"})"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Id" ContentField="Summary"></KanbanCardSettings>
<KanbanSwimlaneSettings KeyField="Assignee" EnableFrozenRows="true"></KanbanSwimlaneSettings>
</SfKanban>Drag and Drop in Blazor Kanban Component
The Kanban component supports dragging cards between columns, swimlanes, and across external components.
Table of Contents
- Default Column Drag and Drop
- Drag and Drop across Swimlanes
- Kanban-to-Kanban Transfer
- Kanban-to-Schedule Transfer
Drag and Drop
Card drag and drop between columns is enabled by default. Set AllowDragAndDrop="false" to disable:
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks" AllowDragAndDrop="false">
<KanbanColumns>
<KanbanColumn HeaderText="Backlog" KeyField="@(new List<string>() {"Open"})"></KanbanColumn>
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() {"InProgress"})"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() {"Close"})"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Id" ContentField="Summary"></KanbanCardSettings>
</SfKanban>You can also control drag/drop per column with AllowDrag and AllowDrop on KanbanColumn.
Drag and Drop across Swimlanes
Enable swimlane-to-swimlane card movement with AllowDragAndDrop on KanbanSwimlaneSettings:
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks">
<KanbanColumns>
<KanbanColumn HeaderText="Backlog" KeyField="@(new List<string>() {"Open"})"></KanbanColumn>
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() {"InProgress"})"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() {"Close"})"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Id" ContentField="Summary"></KanbanCardSettings>
<KanbanSwimlaneSettings KeyField="Assignee" TextField="Assignee" AllowDragAndDrop="true"></KanbanSwimlaneSettings>
</SfKanban>Kanban-to-Kanban
Transfer cards between two separate Kanban boards using ExternalDropId and the DragStop event.
<SfKanban @ref="KanbanRef1" TValue="TasksModel" KeyField="Status" DataSource="Tasks1"
ExternalDropId="@(new List<string>() { "kanban2" })">
<KanbanColumns>
<KanbanColumn HeaderText="Backlog" KeyField="@(new List<string>() {"Open"})"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() {"Close"})"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Id" ContentField="Summary"></KanbanCardSettings>
<KanbanEvents TValue="TasksModel" DragStop="DragStop1"></KanbanEvents>
</SfKanban>
<SfKanban @ref="KanbanRef2" ID="kanban2" TValue="TasksModel" KeyField="Status" DataSource="Tasks2"
ExternalDropId="@(new List<string>() { "kanban1" })">
<KanbanColumns>
<KanbanColumn HeaderText="In Review" KeyField="@(new List<string>() {"Review"})"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() {"Close"})"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Id" ContentField="Summary"></KanbanCardSettings>
<KanbanEvents TValue="TasksModel" DragStop="DragStop2"></KanbanEvents>
</SfKanban>
@code {
SfKanban<TasksModel> KanbanRef1;
SfKanban<TasksModel> KanbanRef2;
public List<TasksModel> Tasks1 = new List<TasksModel>() { /* ... */ };
public List<TasksModel> Tasks2 = new List<TasksModel>() { /* ... */ };
private async Task DragStop1(DragEventArgs<TasksModel> args)
{
// IsExternal is true when the card was dropped onto the other Kanban board
if (args.IsExternal)
{
await KanbanRef1.DeleteCardAsync(args.Data);
await KanbanRef2.AddCardAsync(args.Data, args.DragIndex);
args.Cancel = true;
}
}
private async Task DragStop2(DragEventArgs<TasksModel> args)
{
if (args.IsExternal)
{
await KanbanRef2.DeleteCardAsync(args.Data);
await KanbanRef1.AddCardAsync(args.Data, args.DragIndex);
args.Cancel = true;
}
}
public class TasksModel
{
public string Id { get; set; }
public string Status { get; set; }
public string Summary { get; set; }
}
}UseExternalDropId(typeList<string>) with the target Kanban'sIDattribute value. InDragStop, useargs.IsExternalto detect a cross-board drop. CallDeleteCardAsyncon the source andAddCardAsyncon the target usingargs.DragIndex, then setargs.Cancel = trueto prevent default behavior.
Kanban-to-Schedule
Drag cards from Kanban to a Schedule component and vice versa.
<SfKanban @ref="KanbanObj" TValue="CardData" KeyField="DepartmentName" DataSource="CardDataList"
ExternalDropId="@(new List<string>() { "Schedule" })">
<KanbanColumns>
<KanbanColumn HeaderText="SALES" KeyField="@(new List<string>() {"Sales"})"></KanbanColumn>
<KanbanColumn HeaderText="SUPPORT" KeyField="@(new List<string>() {"Support"})"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Id" ContentField="Summary"></KanbanCardSettings>
<KanbanEvents TValue="CardData" DragStop="KanbanDragStop"></KanbanEvents>
</SfKanban>
<SfSchedule @ref="ScheduleObj" ID="Schedule" TValue="ScheduleData"
DataSource="@ScheduleDataList" AllowDragAndDrop="true">
<ScheduleDragAndDropSettings ExternalDropId="@(new List<string>() { "Kanban" })"></ScheduleDragAndDropSettings>
<ScheduleEvents TValue="ScheduleData" OnActionBegin="ActionBegin"></ScheduleEvents>
<!-- ... ScheduleViews, ScheduleEventSettings -->
</SfSchedule>
@code {
SfKanban<CardData> KanbanObj;
SfSchedule<ScheduleData> ScheduleObj;
public List<CardData> CardDataList = new List<CardData>() { /* ... */ };
public List<ScheduleData> ScheduleDataList = new List<ScheduleData>() { /* ... */ };
private async void KanbanDragStop(DragEventArgs<CardData> args)
{
ScheduleData scheduleData = new ScheduleData()
{
Id = Convert.ToInt32(args.Data[0].Id),
Subject = args.Data[0].Summary,
StartTime = args.DropTime,
EndTime = args.DropTime.AddHours(1),
};
await KanbanObj.DeleteCardAsync(args.Data);
await ScheduleObj.AddEventAsync(scheduleData);
args.Cancel = true;
}
private async void ActionBegin(ActionEventArgs<ScheduleData> args)
{
if (args.ActionType == ActionType.EventRemove && args.CancelType == CancelType.External)
{
CardData cardData = new CardData()
{
Id = args.DeletedEvents[0].Id.ToString(),
Summary = args.DeletedEvents[0].Subject,
DepartmentName = "Sales"
};
await KanbanObj.AddCardAsync(cardData);
}
}
}DragEventArgs Properties
| Property | Type | Description |
|---|---|---|
Data | List<TValue> | Cards being dragged |
DragIndex | int | Index of the dragged card in the source column. Use as the insertion index for AddCardAsync. |
IsExternal | bool | true when the card was dropped onto a different (external) Kanban component. Use this to gate cross-board logic. |
PreviousCardData | TValue | Card data state before the drag began |
Left | double | Client X coordinate of the drop target |
Top | double | Client Y coordinate of the drop target |
Cancel | bool | Set to true to prevent the default drop behaviour (required when manually calling DeleteCardAsync/AddCardAsync) |
Key usage pattern for Kanban-to-Kanban
private async Task OnDragStop(DragEventArgs<TasksModel> args)
{
// Gate on IsExternal — fires for both internal reorders and external drops
if (!args.IsExternal) return;
// Mutate status to match the target board before adding
foreach (var card in args.Data)
card.Status = "To Do";
await SourceKanbanRef.DeleteCardAsync(args.Data);
await TargetKanbanRef.AddCardAsync(args.Data, args.DragIndex);
args.Cancel = true;
}Events in Blazor Kanban Component
Kanban provides events to intercept and customize behavior at key interaction points.
Source: https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Kanban.KanbanEvents-1.html
Table of Contents
- Registering Events
- OnLoad
- Created
- ActionBegin and ActionComplete
- ActionFailure
- CardClick and CardDoubleClick
- CardRendered
- DataBinding
- DialogOpen and DialogClose
- DragStart and DragStop
- QueryCellInfo
- SwimlaneSorting
- All Events Reference
Registering Events
Use the KanbanEvents child component to subscribe to events:
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks">
<KanbanColumns>
<KanbanColumn HeaderText="Backlog" KeyField="@(new List<string>() {"Open"})"></KanbanColumn>
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() {"InProgress"})"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() {"Close"})"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Id" ContentField="Summary"></KanbanCardSettings>
<KanbanEvents TValue="TasksModel"
OnLoad="OnLoadHandler"
ActionBegin="ActionBeginHandler"
ActionComplete="ActionCompleteHandler"
CardClick="CardClickHandler"
DragStart="DragStartHandler"
DragStop="DragStopHandler">
</KanbanEvents>
</SfKanban>OnLoad
Fires once when the Kanban component loads (before initial render). Use this event to make initial configurations or preparations before the Kanban component is fully rendered.
EventCallback: EventCallback<object> Event Arguments: object (generic placeholder — no specific properties defined)
@using Syncfusion.Blazor.Kanban
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="@Tasks">
<KanbanEvents TValue="TasksModel" OnLoad="@OnLoadHandler"></KanbanEvents>
</SfKanban>
@code {
public void OnLoadHandler(Object args)
{
// Component is initializing — make pre-render configurations here
}
}Created
Triggers after the Kanban component is fully created. Use this event to perform setup tasks that require the component to be fully instantiated.
EventCallback: EventCallback<object> Event Arguments: object (generic placeholder — no specific properties defined)
@using Syncfusion.Blazor.Kanban
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="@Tasks">
<KanbanEvents TValue="TasksModel" Created="@CreatedHandler"></KanbanEvents>
</SfKanban>
@code {
public void CreatedHandler(Object args)
{
// Component is fully created — perform post-creation setup here
}
}ActionBegin and ActionComplete
ActionBegin fires before any CRUD action (drag, dialog save/delete). ActionComplete fires after:
private void ActionBeginHandler(ActionEventArgs<TasksModel> args)
{
// args.ActionType: CRUD, DragAndDrop, ColumnToggle, etc.
// args.AddedRecords, args.ChangedRecords, args.DeletedRecords
if (args.RequestType == "CardChanged")
{
// Card was dragged to another column
}
}
private void ActionCompleteHandler(ActionEventArgs<TasksModel> args)
{
// CRUD has completed
Console.WriteLine($"Action complete: {args.RequestType}");
}ActionFailure
Fires when a remote data operation fails:
private void ActionFailureHandler(ActionEventArgs<TasksModel> args)
{
// args.Error: exception details
Console.WriteLine($"Action failed: {args.Error.Message}");
}CardClick and CardDoubleClick
private void CardClickHandler(CardClickEventArgs<TasksModel> args)
{
// args.Data: the clicked card's data
Console.WriteLine($"Card clicked: {args.Data.Id}");
}
private void CardDoubleClickHandler(CardClickEventArgs<TasksModel> args)
{
// Default behavior: opens dialog; set args.Cancel = true to prevent
args.Cancel = false;
}CardRendered
Fires once for each card during rendering. Use it to customize card DOM:
private void CardRenderedHandler(CardRenderedEventArgs<TasksModel> args)
{
// args.Data: card data
// args.Element: the card DOM element reference
}DataBinding
Fires before the Kanban data is bound. Use this event to modify or validate data before it is presented on the board.
EventCallback: EventCallback<DataBindingEventArgs<TValue>>
Event Arguments (`DataBindingEventArgs<TValue>`):
int Count— Gets or sets the count of cards.List<TValue>? Result— Gets or sets the result data intended for binding.
@using Syncfusion.Blazor.Kanban
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="@Tasks">
<KanbanEvents TValue="TasksModel" DataBinding="@DataBindingHandler"></KanbanEvents>
</SfKanban>
@code {
public void DataBindingHandler(DataBindingEventArgs<TasksModel> args)
{
// args.Result: modify or filter data before rendering
// args.Count: total number of incoming records
}
}DialogOpen and DialogClose
`DialogOpen` fires before the dialog opens (cancellable). `DialogClose` fires before the dialog closes.
`DialogOpen` Event Arguments (`DialogOpenEventArgs<TValue>`):
bool Cancel— Set totrueto prevent the dialog from opening.TValue? Data— The card data associated with this dialog action.CurrentAction RequestType— The action type:AddorEdit.
`DialogClose` Event Arguments (`DialogCloseEventArgs<TValue>`):
bool Cancel— Set totrueto prevent the dialog from closing.TValue? Data— The card data associated with this dialog action.string? Interaction— The interaction type that triggered the dialog close.CurrentAction RequestType— The action requested by the dialog.
@using Syncfusion.Blazor.Kanban
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="@Tasks">
<KanbanEvents TValue="TasksModel"
DialogOpen="@DialogOpenHandler"
DialogClose="@DialogCloseHandler">
</KanbanEvents>
</SfKanban>
@code {
public void DialogOpenHandler(DialogOpenEventArgs<TasksModel> args)
{
// Prevent editing cards in 'Close' status
if (args.Data?.Status == "Close")
{
args.Cancel = true;
}
}
public void DialogCloseHandler(DialogCloseEventArgs<TasksModel> args)
{
Console.WriteLine($"Dialog closed. Interaction: {args.Interaction}");
}
}DragStart and DragStop
`DragStart` fires when a card drag begins. `DragStop` fires when the drag ends (card is dropped).
Event Arguments (`DragEventArgs<TValue>`):
bool Cancel— Set totrueto cancel the drag or drop action.List<TValue>? Data— The card data objects being dragged.int DragIndex— The index of the dragged/dropped element.bool IsExternal— Whether the drop is to an external component.double Left— Client X coordinate of the cursor.List<TValue>? PreviousCardData— Data of the card that was previously at the drop position.double Top— Client Y coordinate of the cursor.
@using Syncfusion.Blazor.Kanban
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="@Tasks">
<KanbanEvents TValue="TasksModel"
DragStart="@DragStartHandler"
DragStop="@DragStopHandler">
</KanbanEvents>
</SfKanban>
@code {
public void DragStartHandler(DragEventArgs<TasksModel> args)
{
// args.Data: list of cards being dragged
Console.WriteLine($"Drag started for {args.Data?.Count} card(s)");
}
public void DragStopHandler(DragEventArgs<TasksModel> args)
{
// args.Data: dropped card data; args.IsExternal: dropped outside Kanban
Console.WriteLine($"Card dropped. External: {args.IsExternal}");
}
}QueryCellInfo
Fires before each column cell is rendered. Use to customize column cell appearance or inject additional data.
EventCallback: EventCallback<QueryCellInfoEventArgs<TValue>>
Event Arguments (`QueryCellInfoEventArgs<TValue>`):
bool Cancel— Set totrueto cancel the rendering action.List<SwimlaneSettingsModel>? Data— Data associated with the cell being rendered.string? RequestType— The request type of the current action.
@using Syncfusion.Blazor.Kanban
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="@Tasks">
<KanbanEvents TValue="TasksModel" QueryCellInfo="@QueryCellInfoHandler"></KanbanEvents>
</SfKanban>
@code {
public void QueryCellInfoHandler(QueryCellInfoEventArgs<TasksModel> args)
{
// Customize cell rendering based on column key, swimlane, etc.
}
}SwimlaneSorting
Fires before swimlane rows are rendered/sorted. Use to manage or customize swimlane row ordering.
EventCallback: EventCallback<SwimlaneSortEventArgs>
Event Arguments (`SwimlaneSortEventArgs`):
List<SwimlaneSettingsModel>? SwimlaneRows— Gets or sets the sorting order of swimlane rows.
@using Syncfusion.Blazor.Kanban
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="@Tasks">
<KanbanSwimlaneSettings KeyField="Assignee"></KanbanSwimlaneSettings>
<KanbanEvents TValue="TasksModel" SwimlaneSorting="@SwimlaneSortingHandler"></KanbanEvents>
</SfKanban>
@code {
public void SwimlaneSortingHandler(SwimlaneSortEventArgs args)
{
// args.SwimlaneRows: modify the order of swimlane rows here
}
}All Events Reference
| Event | EventCallback Type | Cancellable | Description |
|---|---|---|---|
OnLoad | EventCallback<object> | No | Fires when the component loads, before initial render |
Created | EventCallback<object> | No | Fires after the component is fully created |
ActionBegin | EventCallback<ActionEventArgs<TValue>> | Yes | Fires before any CRUD action begins |
ActionComplete | EventCallback<ActionEventArgs<TValue>> | No | Fires after a CRUD action succeeds |
ActionFailure | EventCallback<ActionEventArgs<TValue>> | No | Fires when a CRUD action fails |
CardClick | EventCallback<CardClickEventArgs<TValue>> | Yes | Fires on single click of a card |
CardDoubleClick | EventCallback<CardClickEventArgs<TValue>> | Yes | Fires on double-click of a card (opens dialog by default) |
CardRendered | EventCallback<CardRenderedEventArgs<TValue>> | Yes | Fires before each card is rendered |
DataBinding | EventCallback<DataBindingEventArgs<TValue>> | No | Fires before data is bound to the component |
DialogClose | EventCallback<DialogCloseEventArgs<TValue>> | Yes | Fires before the editing dialog closes |
DialogOpen | EventCallback<DialogOpenEventArgs<TValue>> | Yes | Fires before the editing dialog opens |
DragStart | EventCallback<DragEventArgs<TValue>> | Yes | Fires when a card drag operation begins |
DragStop | EventCallback<DragEventArgs<TValue>> | Yes | Fires when a card drag operation ends |
QueryCellInfo | EventCallback<QueryCellInfoEventArgs<TValue>> | Yes | Fires before each column cell is rendered |
SwimlaneSorting | EventCallback<SwimlaneSortEventArgs> | No | Fires before swimlane rows are sorted/rendered |
Getting Started with Blazor Kanban Component
This guide covers setup for Blazor WebAssembly, Blazor Server, and Blazor Web App projects.
Prerequisites
- System requirements for Blazor components
- .NET SDK installed
Install NuGet Packages
Visual Studio (Package Manager Console)
Install-Package Syncfusion.Blazor.Kanban -Version {{ site.releaseversion }}
Install-Package Syncfusion.Blazor.Themes -Version {{ site.releaseversion }}.NET CLI
dotnet add package Syncfusion.Blazor.Kanban -v {{ site.releaseversion }}
dotnet add package Syncfusion.Blazor.Themes -v {{ site.releaseversion }}
dotnet restoreRegister Syncfusion Blazor Service
Blazor WebAssembly (Program.cs)
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Syncfusion.Blazor;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.Services.AddSyncfusionBlazor();
await builder.Build().RunAsync();Blazor Server App (Program.cs)
using Syncfusion.Blazor;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddSyncfusionBlazor();
var app = builder.Build();Blazor Web App (Program.cs — both server and client projects)
// Server project
using Syncfusion.Blazor;
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents()
.AddInteractiveWebAssemblyComponents();
builder.Services.AddSyncfusionBlazor();// Client project
using Syncfusion.Blazor;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.Services.AddSyncfusionBlazor();
await builder.Build().RunAsync();Add Import Namespaces (_Imports.razor)
@using Syncfusion.Blazor
@using Syncfusion.Blazor.KanbanAdd Stylesheet and Script Resources
Blazor WebAssembly (wwwroot/index.html)
<head>
<link href="_content/Syncfusion.Blazor.Themes/bootstrap5.css" rel="stylesheet" />
<script src="_content/Syncfusion.Blazor.Core/scripts/syncfusion-blazor.min.js" type="text/javascript"></script>
</head>Blazor Server / Web App (Components/App.razor)
<head>
<link href="_content/Syncfusion.Blazor.Themes/bootstrap5.css" rel="stylesheet" />
</head>
<body>
<script src="_content/Syncfusion.Blazor.Core/scripts/syncfusion-blazor.min.js" type="text/javascript"></script>
</body>Add the Kanban Component
Blazor WebAssembly (Pages/Index.razor)
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks">
<KanbanColumns>
<KanbanColumn HeaderText="To Do" KeyField="@(new List<string>() {"Open"})"></KanbanColumn>
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() {"InProgress"})"></KanbanColumn>
<KanbanColumn HeaderText="Testing" KeyField="@(new List<string>() {"Testing"})"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() {"Close"})"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Title" ContentField="Summary"></KanbanCardSettings>
</SfKanban>
@code {
public class TasksModel
{
public string Id { get; set; }
public string Title { get; set; }
public string Status { get; set; }
public string Summary { get; set; }
}
public List<TasksModel> Tasks = new List<TasksModel>()
{
new TasksModel { Id = "Task 1", Title = "BLAZ-29001", Status = "Open", Summary = "Analyze the new requirements gathered from the customer." },
new TasksModel { Id = "Task 2", Title = "BLAZ-29002", Status = "Open", Summary = "Show the retrieved data from the server in grid control." },
new TasksModel { Id = "Task 3", Title = "BLAZ-29003", Status = "InProgress", Summary = "Improve application performance" },
new TasksModel { Id = "Task 4", Title = "BLAZ-29004", Status = "Testing", Summary = "Fix the issues reported by the customer." },
new TasksModel { Id = "Task 5", Title = "BLAZ-29005", Status = "Testing", Summary = "Fix the issues reported in Safari browser." },
};
}Blazor Server App (Components/Pages/Home.razor)
Add @rendermode InteractiveServer at the top if using per-page/component interactivity:
@rendermode InteractiveServer
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks">
<KanbanColumns>
<KanbanColumn HeaderText="To Do" KeyField="@(new List<string>() {"Open"})"></KanbanColumn>
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() {"InProgress"})"></KanbanColumn>
<KanbanColumn HeaderText="Testing" KeyField="@(new List<string>() {"Testing"})"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() {"Close"})"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Title" ContentField="Summary"></KanbanCardSettings>
</SfKanban>Enable Swimlane
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks">
<KanbanColumns>
<KanbanColumn HeaderText="To Do" KeyField="@(new List<string>() {"Open"})"></KanbanColumn>
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() {"InProgress"})"></KanbanColumn>
<KanbanColumn HeaderText="Testing" KeyField="@(new List<string>() {"Testing"})"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() {"Close"})"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Title" ContentField="Summary"></KanbanCardSettings>
<KanbanSwimlaneSettings KeyField="Assignee"></KanbanSwimlaneSettings>
</SfKanban>
@code {
public class TasksModel
{
public string Id { get; set; }
public string Title { get; set; }
public string Status { get; set; }
public string Summary { get; set; }
public string Assignee { get; set; }
}
public List<TasksModel> Tasks = new List<TasksModel>()
{
new TasksModel { Id = "Task 1", Title = "BLAZ-29001", Status = "Open", Summary = "Analyze the new requirements gathered from the customer.", Assignee = "Nancy Davloio" },
new TasksModel { Id = "Task 2", Title = "BLAZ-29002", Status = "InProgress", Summary = "Improve application performance", Assignee = "Andrew Fuller" },
new TasksModel { Id = "Task 3", Title = "BLAZ-29003", Status = "Open", Summary = "Arrange a web meeting with the customer to get new requirements.", Assignee = "Janet Leverling" },
new TasksModel { Id = "Task 4", Title = "BLAZ-29004", Status = "InProgress", Summary = "Fix the issues reported in the IE browser.", Assignee = "Janet Leverling" },
new TasksModel { Id = "Task 5", Title = "BLAZ-29005", Status = "Review", Summary = "Fix the issues reported by the customer.", Assignee = "Steven walker" },
};
}Render Mode Reference (Blazor Web App)
| Interactivity location | RenderMode | Code |
|---|---|---|
| Per page/component | Auto | @rendermode InteractiveAuto |
| Per page/component | WebAssembly | @rendermode InteractiveWebAssembly |
| Per page/component | Server | @rendermode InteractiveServer |
| Global | Any | Configured in App.razor |
Localization in Blazor Kanban Component
The Kanban component supports localization of text strings and RTL (Right-to-Left) layout for international audiences.
Table of Contents
Setting the Locale
Use the Locale property to load locale-specific text. The locale package must be registered in the app:
@using Syncfusion.Blazor.Kanban
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks" Locale="ar">
<KanbanColumns>
<KanbanColumn HeaderText="Backlog" KeyField="@(new List<string>() {"Open"})"></KanbanColumn>
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() {"InProgress"})"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() {"Close"})"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Id" ContentField="Summary"></KanbanCardSettings>
</SfKanban>Registering Locale Data
Add the locale data to your Program.cs (or startup configuration):
using Syncfusion.Blazor;
// Register locale data
var culture = new CultureInfo("ar");
CultureInfo.DefaultThreadCurrentCulture = culture;
CultureInfo.DefaultThreadCurrentUICulture = culture;Or load locale JSON data at runtime:
// In wwwroot/js/loadLocale.js
window.loadLocale = async function (locale) {
const data = await fetch(`/locales/${locale}.json`);
const json = await data.json();
ej.base.L10n.load(json);
};RTL (Right-to-Left) Mode
Enable RTL layout for Arabic, Hebrew, and other RTL languages with EnableRtl:
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks"
Locale="ar" EnableRtl="true">
<KanbanColumns>
<KanbanColumn HeaderText="في المعالجة" KeyField="@(new List<string>() {"Open"})"></KanbanColumn>
<KanbanColumn HeaderText="قيد التنفيذ" KeyField="@(new List<string>() {"InProgress"})"></KanbanColumn>
<KanbanColumn HeaderText="مكتمل" KeyField="@(new List<string>() {"Close"})"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Id" ContentField="Summary"></KanbanCardSettings>
</SfKanban>When RTL is enabled:
- Columns render from right to left
- Text alignment is right-aligned
- Card drag direction is reversed
- Dialog layout mirrors for RTL reading
RTL with Swimlanes
RTL also applies to swimlane rows:
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks"
Locale="ar" EnableRtl="true">
<KanbanColumns>
<KanbanColumn HeaderText="في المعالجة" KeyField="@(new List<string>() {"Open"})"></KanbanColumn>
<KanbanColumn HeaderText="قيد التنفيذ" KeyField="@(new List<string>() {"InProgress"})"></KanbanColumn>
<KanbanColumn HeaderText="مكتمل" KeyField="@(new List<string>() {"Close"})"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Id" ContentField="Summary"></KanbanCardSettings>
<KanbanSwimlaneSettings KeyField="Assignee" TextField="Assignee"></KanbanSwimlaneSettings>
</SfKanban>Localization Properties Reference
| Property | Type | Description |
|---|---|---|
Locale | string | Locale code (e.g., "ar", "fr", "de") for translating UI strings |
EnableRtl | bool | Enable right-to-left layout (default: false) |
Localizable String Keys
The following Kanban string keys can be overridden in locale files:
| Key | Default Value | Description |
|---|---|---|
Kanban_Items | "items" | Items label in column header |
Kanban_Min | "Min" | Minimum constraint label |
Kanban_Max | "Max" | Maximum constraint label |
Kanban_Cards | "Cards" | Cards label |
Kanban_EmptyContent | "No cards to display" | Empty column message |
Kanban_EmptyFilters | "No records" | Empty filter message |
Kanban_AddTitle | "Add New Card" | Dialog title when adding |
Kanban_EditTitle | "Edit Card" | Dialog title when editing |
Kanban_DeleteContent | "Are you sure you want to delete this card?" | Delete confirmation |
Kanban_DeleteTitle | "Delete Card" | Delete dialog title |
````markdown
SfKanban Public Methods Reference
All public methods available on the SfKanban<TValue> component instance accessed via @ref.
Source: https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Kanban.SfKanban-1.html#methods Namespace: Syncfusion.Blazor.Kanban
Table of Contents
- Getting a Component Reference
- Card Management
- AddCardAsync
- UpdateCardAsync
- DeleteCardAsync
- Column Management
- DeleteColumnAsync
- Data Retrieval
- GetColumnDataByKeys
- GetSwimlaneData
- GetTargetDetailsAsync
- Dialog Control
- OpenDialogAsync
- CloseDialogAsync
- Board Control
- RefreshAsync
- ShowSpinnerAsync
- HideSpinnerAsync
- UpdateViewDataAsync
- Methods Summary Table
---
Getting a Component Reference
Use @ref to capture the SfKanban instance and call methods on it:
<SfKanban @ref="kanbanRef" TValue="TasksModel" KeyField="Status" DataSource="@Tasks">
<KanbanColumns>
<KanbanColumn HeaderText="To Do" KeyField="@(new List<string>() { "Open" })"></KanbanColumn>
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() { "InProgress" })"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() { "Close" })"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Title" ContentField="Summary"></KanbanCardSettings>
</SfKanban>
@code {
private SfKanban<TasksModel> kanbanRef;
// Use kanbanRef to call methods such as AddCardAsync, RefreshAsync, etc.
}---
Card Management
AddCardAsync
Adds one or more new cards to the Kanban data source.
Overloads
| Signature | Description |
|---|---|
AddCardAsync(TValue cardData, int index = 0) | Adds a single card at the specified index. |
AddCardAsync(List<TValue> cardData, int index = 0) | Adds multiple cards at the specified index. |
Returns: Task
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
cardData | TValue or List<TValue> | Yes | The card data object(s) to add. |
index | int | No (default: 0) | Zero-based index position within the column to insert the card. |
<button @onclick="AddSingleCard">Add Card</button>
<button @onclick="AddMultipleCards">Add Multiple Cards</button>
@code {
private async Task AddSingleCard()
{
var newCard = new TasksModel
{
Id = "Task 100",
Title = "BLAZ-30001",
Status = "Open",
Summary = "New task added programmatically.",
Assignee = "Nancy Davloio"
};
await kanbanRef.AddCardAsync(newCard, 0);
}
private async Task AddMultipleCards()
{
var newCards = new List<TasksModel>
{
new TasksModel { Id = "Task 101", Title = "BLAZ-30002", Status = "Open", Summary = "Task A" },
new TasksModel { Id = "Task 102", Title = "BLAZ-30003", Status = "InProgress", Summary = "Task B" }
};
await kanbanRef.AddCardAsync(newCards);
}
}---
UpdateCardAsync
Updates one or more existing cards in the Kanban data source.
Overloads
| Signature | Description |
|---|---|
UpdateCardAsync(TValue cardData, int index) | Updates a single card at the specified index. |
UpdateCardAsync(List<TValue> cardData, int index) | Updates multiple cards at the specified index. |
Returns: Task Throws: Exception
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
cardData | TValue or List<TValue> | Yes | The updated card data object(s). |
index | int | Yes | The index position at which to update. |
<button @onclick="UpdateCard">Update Card</button>
@code {
private async Task UpdateCard()
{
var updatedCard = new TasksModel
{
Id = "Task 1",
Title = "BLAZ-29001",
Status = "InProgress", // moved to a different column
Summary = "Updated summary text.",
Assignee = "Andrew Fuller"
};
await kanbanRef.UpdateCardAsync(updatedCard, 0);
}
}---
DeleteCardAsync
Deletes one or more cards from the Kanban data source.
Overloads
| Signature | Description |
|---|---|
DeleteCardAsync(TValue cardData) | Deletes a card using the full card data object. |
DeleteCardAsync(List<TValue> cardData) | Deletes multiple cards using a list of card data objects. |
DeleteCardAsync(int id) | Deletes a card by its integer primary key. |
DeleteCardAsync(string id) | Deletes a card by its string primary key. |
Returns: Task
<button @onclick="DeleteByObject">Delete Card (Object)</button>
<button @onclick="DeleteById">Delete Card (ID)</button>
@code {
private async Task DeleteByObject()
{
// Delete using the full data object
await kanbanRef.DeleteCardAsync(Tasks[0]);
}
private async Task DeleteById()
{
// Delete using string ID
await kanbanRef.DeleteCardAsync("Task 1");
}
}---
Column Management
DeleteColumnAsync
Deletes a column from the Kanban board at the specified index.
Signature: DeleteColumnAsync(int index) Returns: Task
| Name | Type | Required | Description |
|---|---|---|---|
index | int | Yes | Zero-based index of the column to delete. |
<button @onclick="RemoveLastColumn">Remove Last Column</button>
@code {
private async Task RemoveLastColumn()
{
// Delete the last column (index 3 for a 4-column board)
await kanbanRef.DeleteColumnAsync(3);
}
}---
Data Retrieval
GetColumnDataByKeys
Returns all card data records belonging to the columns matching the provided key field values.
Signature: GetColumnDataByKeys(List<string> keys) Returns: List<TValue>
| Name | Type | Required | Description |
|---|---|---|---|
keys | List<string> | Yes | The column key field values to retrieve data for. |
<button @onclick="GetOpenCards">Get Open Column Data</button>
@code {
private void GetOpenCards()
{
var openCards = kanbanRef.GetColumnDataByKeys(new List<string> { "Open" });
Console.WriteLine($"Open cards count: {openCards.Count}");
// Get data from multiple column keys
var activeCards = kanbanRef.GetColumnDataByKeys(new List<string> { "Open", "InProgress" });
}
}---
GetSwimlaneData
Returns all card data records belonging to the specified swimlane row.
Signature: GetSwimlaneData(string keyField) Returns: List<TValue>
| Name | Type | Required | Description |
|---|---|---|---|
keyField | string | Yes | The swimlane key field value (e.g., an assignee name) to retrieve data for. |
<button @onclick="GetAssigneeData">Get Assignee's Cards</button>
@code {
private void GetAssigneeData()
{
var assigneeCards = kanbanRef.GetSwimlaneData("Nancy Davloio");
Console.WriteLine($"Cards assigned to Nancy: {assigneeCards.Count}");
}
}---
GetTargetDetailsAsync
Returns card and column details based on the mouse cursor's left/top screen coordinates. Useful for custom drag-and-drop integrations.
Signature: GetTargetDetailsAsync(double left, double top) Returns: Task<KanbanTargetDetails<TValue>>
| Name | Type | Required | Description |
|---|---|---|---|
left | double | Yes | The client X (horizontal) coordinate. |
top | double | Yes | The client Y (vertical) coordinate. |
Sub-type: `KanbanTargetDetails<TValue>` Properties
| Property | Type | Default | Description |
|---|---|---|---|
ColumnKeyField | string? | "" | Gets or sets the column key field based on the mouse cursor position during drag-and-drop. |
CurrentCardId | string? | null | Gets or sets the current card ID based on the cursor position. |
Index | int | 0 | Gets or sets the current card position (index) in the column. |
PreviousCardData | List<TValue>? | null | Gets or sets the data of the previous card; used to retrieve state during reordering. |
PreviousCardId | string? | null | Gets or sets the previous card ID based on cursor position; crucial when SortOrderBy is Index. |
SwimlaneKeyField | string? | null | Gets or sets the swimlane key field based on current mouse position. |
@code {
private async Task OnCustomDrop(double clientX, double clientY)
{
var target = await kanbanRef.GetTargetDetailsAsync(clientX, clientY);
Console.WriteLine($"Column: {target.ColumnKeyField}");
Console.WriteLine($"Card at position: {target.CurrentCardId} (index {target.Index})");
Console.WriteLine($"Previous card: {target.PreviousCardId}");
Console.WriteLine($"Swimlane: {target.SwimlaneKeyField}");
}
}---
Dialog Control
OpenDialogAsync
Programmatically opens the card editing dialog for a given action and card data.
Signature: OpenDialogAsync(CurrentAction action, TValue data) Returns: Task
| Name | Type | Required | Description |
|---|---|---|---|
action | CurrentAction | Yes | The dialog action: Add, Edit, or Delete. |
data | TValue | Yes | The card data to display/edit in the dialog. |
<button @onclick="OpenAddDialog">Add New Card via Dialog</button>
<button @onclick="() => OpenEditDialog(Tasks[0])">Edit First Card</button>
@code {
private async Task OpenAddDialog()
{
await kanbanRef.OpenDialogAsync(CurrentAction.Add, new TasksModel());
}
private async Task OpenEditDialog(TasksModel card)
{
await kanbanRef.OpenDialogAsync(CurrentAction.Edit, card);
}
}---
CloseDialogAsync
Programmatically closes the card editing dialog.
Signature: CloseDialogAsync() Returns: Task
<button @onclick="CloseDialog">Close Dialog</button>
@code {
private async Task CloseDialog()
{
await kanbanRef.CloseDialogAsync();
}
}---
Board Control
RefreshAsync
Refreshes the entire Kanban board, re-rendering the header and content to reflect the latest data state.
Signature: RefreshAsync() Returns: Task Throws: Exception
<button @onclick="RefreshBoard">Refresh Board</button>
@code {
private async Task RefreshBoard()
{
await kanbanRef.RefreshAsync();
}
}---
ShowSpinnerAsync
Manually displays the loading spinner over the Kanban board to indicate a processing operation.
Signature: ShowSpinnerAsync() Returns: Task Throws: Exception
@code {
private async Task LoadData()
{
await kanbanRef.ShowSpinnerAsync();
// Perform long-running operation
await FetchRemoteData();
await kanbanRef.HideSpinnerAsync();
}
}---
HideSpinnerAsync
Manually hides the loading spinner.
Signature: HideSpinnerAsync() Returns: Task
@code {
private async Task HideSpinner()
{
await kanbanRef.HideSpinnerAsync();
}
}---
UpdateViewDataAsync
Asynchronously replaces the Kanban board's current data with a new data set.
Signature: UpdateViewDataAsync(IEnumerable<TValue> data) Returns: Task Throws: Exception
| Name | Type | Required | Description |
|---|---|---|---|
data | IEnumerable<TValue> | Yes | The new data set to render on the board. |
<button @onclick="SwitchDataSet">Switch Data Set</button>
@code {
private async Task SwitchDataSet()
{
var newData = await FetchUpdatedTasksFromServer();
await kanbanRef.UpdateViewDataAsync(newData);
}
}---
Methods Summary Table
| Method | Returns | Description |
|---|---|---|
AddCardAsync(TValue, int) | Task | Add a single card at an index |
AddCardAsync(List<TValue>, int) | Task | Add multiple cards at an index |
UpdateCardAsync(TValue, int) | Task | Update a single card |
UpdateCardAsync(List<TValue>, int) | Task | Update multiple cards |
DeleteCardAsync(TValue) | Task | Delete card by data object |
DeleteCardAsync(List<TValue>) | Task | Delete multiple cards by data objects |
DeleteCardAsync(int) | Task | Delete card by integer ID |
DeleteCardAsync(string) | Task | Delete card by string ID |
DeleteColumnAsync(int) | Task | Delete a column by index |
GetColumnDataByKeys(List<string>) | List<TValue> | Retrieve cards in specified columns |
GetSwimlaneData(string) | List<TValue> | Retrieve cards in a swimlane row |
GetTargetDetailsAsync(double, double) | Task<KanbanTargetDetails<TValue>> | Get card/column at screen coordinates |
OpenDialogAsync(CurrentAction, TValue) | Task | Open card dialog programmatically |
CloseDialogAsync() | Task | Close card dialog programmatically |
RefreshAsync() | Task | Re-render the full board |
ShowSpinnerAsync() | Task | Show the loading spinner |
HideSpinnerAsync() | Task | Hide the loading spinner |
UpdateViewDataAsync(IEnumerable<TValue>) | Task | Replace board data with a new data set |
````
````markdown
SfKanban Properties Reference
All configurable properties for the SfKanban<TValue> component and its sub-components.
Source: https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Kanban.SfKanban-1.html#properties
Table of Contents
- SfKanban Core Properties
- [KanbanCardSettings](#kanbancards settings)
- KanbanColumn
- [KanbanDialogSettings](#kanbandialog settings)
- KanbanSwimlaneSettings
- KanbanSortSettings
- KanbanStackedHeader
- ConstraintType Enum
---
SfKanban Core Properties
AllowDragAndDrop
Type: [Parameter] public bool AllowDragAndDrop { get; set; } Default: true Gets or sets a value indicating whether drag and drop actions are enabled in the Kanban.
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks"
AllowDragAndDrop="false">
</SfKanban>---
AllowKeyboard
Type: [Parameter] public bool AllowKeyboard { get; set; } Default: true Gets or sets a value indicating whether keyboard interaction is enabled in the Kanban board.
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks"
AllowKeyboard="true">
</SfKanban>---
ConstraintType
Type: [Parameter] public ConstraintType? ConstraintType { get; set; } Default: null Defines the constraint type used to apply WIP validation based on column or swimlane. Possible values: Column and Swimlane.
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks"
ConstraintType="ConstraintType.Column">
</SfKanban>---
CssClass
Type: [Parameter] public string? CssClass { get; set; } Default: null Used to customize the Kanban by applying custom CSS class names for specific styles and themes.
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks"
CssClass="custom-kanban">
</SfKanban>---
DataSource
Type: [Parameter] [JsonIgnore] public IEnumerable<TValue>? DataSource { get; set; } Default: null Binds the list items either through local or remote service and assigns them to the component.
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="@Tasks">
</SfKanban>---
DataSourceChanged
Type: [Parameter] public EventCallback<IEnumerable<TValue>>? DataSourceChanged { get; set; } Default: null Invoked when the data source changes. Use for two-way data binding.
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="@Tasks"
DataSourceChanged="@OnDataSourceChanged">
</SfKanban>
@code {
private void OnDataSourceChanged(IEnumerable<TasksModel> data)
{
Tasks = data.ToList();
}
}---
EnableRtl
Type: [Parameter] public bool EnableRtl { get; set; } Default: false Enables or disables rendering of the component in the right-to-left direction.
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks"
EnableRtl="true">
</SfKanban>---
EnableTooltip
Type: [Parameter] public bool EnableTooltip { get; set; } Default: false Gets or sets a value indicating whether tooltips are enabled in the Kanban board. Shows card details on hover.
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks"
EnableTooltip="true">
</SfKanban>---
ExternalDropId
Type: [Parameter] public List<string>? ExternalDropId { get; set; } Default: null Defines the IDs of external drop target components (e.g., another Kanban or Scheduler) on which cards can be dropped.
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks"
ExternalDropId="@(new List<string>() { "ScheduleBoard" })">
</SfKanban>---
Height
Type: [Parameter] public string? Height { get; set; } Default: "auto" Specifies the height of the Kanban component. Accepts string values like "500px" or "100%".
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks"
Height="600px">
</SfKanban>---
ID
Type: [Parameter] public string? ID { get; set; } Default: null Gets or sets the ID of the Kanban component. Required when using ExternalDropId across components.
<SfKanban ID="KanbanBoard1" TValue="TasksModel" KeyField="Status" DataSource="Tasks">
</SfKanban>---
KeyField
Type: [Parameter] public string? KeyField { get; set; } Default: (none) Required. Defines the key field of the Kanban board. This field determines which column a card belongs to, matching its value against the KeyField values defined in each KanbanColumn.
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks">
</SfKanban>---
Locale
Type: [Parameter] public string? Locale { get; set; } Default: "en-US" Gets or sets the locale of the Kanban component for localization/internationalization.
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks"
Locale="fr-FR">
</SfKanban>---
Query
Type: public Query? Query { get; set; } Default: null Defines the query used for filtering/sorting data when binding from a remote data source.
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="@RemoteData"
Query="@KanbanQuery">
...
</SfKanban>
@code {
private Query KanbanQuery = new Query().Where("Status", "notequal", "Archived");
}---
KanbanCardSettings
Configured via the <KanbanCardSettings> child component or the CardSettings property. Defines card header, content, template, and tooltip behavior.
| Property | Type | Default | Description |
|---|---|---|---|
ContentField | string? | null | Maps the data field displayed in the card body. |
EnableTooltip | bool? | null | Enables or disables tooltip for individual cards. Overrides the board-level EnableTooltip. |
HeaderField | string? | null | Maps the data field displayed in the card header (unique identifier). |
ShowHeader | bool? | true | Shows or hides the card header. |
Template | string? | null | Gets or sets a custom Razor template for the card content. |
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks">
<KanbanCardSettings HeaderField="Title" ContentField="Summary" ShowHeader="true">
</KanbanCardSettings>
</SfKanban>With custom card template:
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks">
<KanbanCardSettings HeaderField="Title">
<Template>
@{
var task = (context as TasksModel);
<div class="card-template">
<div class="card-header">@task.Title</div>
<div class="card-body">@task.Summary</div>
<div class="card-footer">Assignee: @task.Assignee</div>
</div>
}
</Template>
</KanbanCardSettings>
</SfKanban>---
KanbanColumn
Configured via <KanbanColumn> inside <KanbanColumns>. Defines each column of the board.
| Property | Type | Default | Description |
|---|---|---|---|
AllowAdding | bool | false | Enables or disables the "Add card" button at the top of the column. |
AllowDrag | bool | true | Enables or disables dragging of cards out of this column. |
AllowDrop | bool | true | Enables or disables dropping of cards into this column. |
AllowToggle | bool | true | Enables or disables expand/collapse toggle for this column. |
HeaderText | string? | null | The display text for the column header. |
KeyField | List<string> | (required) | The status values that map cards to this column. Supports multiple values. |
MaxCount | int? | null | Maximum card count allowed (WIP limit). Shows a warning when exceeded. |
MinCount | int? | null | Minimum card count required (WIP limit). Shows a warning when below threshold. |
ShowItemCount | bool | true | Shows or hides the item count badge in the column header. |
Template | string? | null | Custom Razor template for the column header. |
TransitionColumns | List<string>? | null | Restricts which columns a card can be dropped into from this column. |
<KanbanColumns>
<KanbanColumn HeaderText="Backlog"
KeyField="@(new List<string>() { "Open" })"
AllowAdding="true"
MinCount="2">
</KanbanColumn>
<KanbanColumn HeaderText="In Progress"
KeyField="@(new List<string>() { "InProgress" })"
MaxCount="3"
AllowToggle="true">
</KanbanColumn>
<KanbanColumn HeaderText="Done"
KeyField="@(new List<string>() { "Close" })"
AllowDrag="false">
</KanbanColumn>
</KanbanColumns>---
KanbanDialogSettings
Configured via the <KanbanDialogSettings> child component. Controls the card editing dialog behavior.
| Property | Type | Default | Description |
|---|---|---|---|
AllowDragging | bool | false | Enables or disables dragging the dialog window. |
AnimationSettings | DialogAnimationSettings? | null | Animation settings (effect, duration, delay) for dialog open/close. |
CssClass | string? | null | Custom CSS class for the dialog element. |
EnableResize | bool | false | Enables or disables resizing the dialog window. |
Fields | string? | null | Specifies the fields to show in the auto-generated dialog form. |
ShowCloseIcon | bool | true | Shows or hides the close (X) icon in the dialog header. |
Template | string? | null | Custom Razor template for the entire dialog content. |
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks">
<KanbanDialogSettings AllowDragging="true" EnableResize="true">
</KanbanDialogSettings>
</SfKanban>With custom dialog template:
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks">
<KanbanDialogSettings>
<Template>
@{
var task = (context as TasksModel);
<div>
<label>Title: <input @bind="task.Title" /></label>
<label>Status: <input @bind="task.Status" /></label>
</div>
}
</Template>
</KanbanDialogSettings>
</SfKanban>---
KanbanSwimlaneSettings
Configured via the <KanbanSwimlaneSettings> child component. Groups cards into horizontal swimlane rows.
| Property | Type | Default | Description |
|---|---|---|---|
AllowDragAndDrop | bool | true | Enables or disables drag-and-drop between different swimlane rows. |
KeyField | string? | null | The data field used to group cards into swimlane rows. |
ShowEmptySwimlane | bool | false | Shows or hides swimlane rows that have no cards. |
Template | string? | null | Custom Razor template for swimlane row headers. |
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks">
<KanbanSwimlaneSettings KeyField="Assignee"
ShowEmptySwimlane="true"
AllowDragAndDrop="true">
</KanbanSwimlaneSettings>
</SfKanban>---
KanbanSortSettings
Configured via the <KanbanSortSettings> child component. Controls the ordering of cards within columns.
| Property | Type | Default | Description |
|---|---|---|---|
Direction | SortDirection | Ascending | Sort direction: Ascending or Descending. |
Field | string? | null | The data field used for sorting cards. Required when SortBy is Index or Custom. |
SortBy | SortOrderBy | DataSourceOrder | Sorting mode: DataSourceOrder, Index, or Custom. |
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks">
<KanbanSortSettings SortBy="SortOrderBy.Index"
Field="RankId"
Direction="SortDirection.Ascending">
</KanbanSortSettings>
</SfKanban>---
KanbanStackedHeader
Configured via <KanbanStackedHeader> inside <KanbanStackedHeaders>. Groups multiple columns under a shared header label.
| Property | Type | Default | Description |
|---|---|---|---|
HeaderText | string? | null | Display text shown in the stacked header cell. |
KeyField | string? | null | Comma-separated column KeyField values this stacked header spans. |
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks">
<KanbanColumns>
<KanbanColumn HeaderText="Open" KeyField="@(new List<string>() { "Open" })"></KanbanColumn>
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() { "InProgress" })"></KanbanColumn>
<KanbanColumn HeaderText="Testing" KeyField="@(new List<string>() { "Testing" })"></KanbanColumn>
<KanbanColumn HeaderText="Close" KeyField="@(new List<string>() { "Close" })"></KanbanColumn>
</KanbanColumns>
<KanbanStackedHeaders>
<KanbanStackedHeader HeaderText="To Do" KeyField="Open"></KanbanStackedHeader>
<KanbanStackedHeader HeaderText="Development" KeyField="InProgress,Testing"></KanbanStackedHeader>
<KanbanStackedHeader HeaderText="Done" KeyField="Close"></KanbanStackedHeader>
</KanbanStackedHeaders>
</SfKanban>---
ConstraintType Enum
Defines the scope at which WIP (Work-In-Progress) validation limits are enforced.
| Value | Description |
|---|---|
Column | WIP constraint (MinCount/MaxCount) is validated per column across all swimlane rows combined. |
Swimlane | WIP constraint is validated per column per swimlane row independently. |
<!-- Column-level WIP validation (default) -->
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks"
ConstraintType="ConstraintType.Column">
<KanbanColumns>
<KanbanColumn HeaderText="In Progress"
KeyField="@(new List<string>() { "InProgress" })"
MaxCount="5">
</KanbanColumn>
</KanbanColumns>
</SfKanban>
<!-- Swimlane-level WIP validation -->
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks"
ConstraintType="ConstraintType.Swimlane">
<KanbanSwimlaneSettings KeyField="Assignee"></KanbanSwimlaneSettings>
<KanbanColumns>
<KanbanColumn HeaderText="In Progress"
KeyField="@(new List<string>() { "InProgress" })"
MaxCount="3">
</KanbanColumn>
</KanbanColumns>
</SfKanban>---
Quick Reference Table
| Property | Component | Type | Default | Description |
|---|---|---|---|---|
AllowDragAndDrop | SfKanban | bool | true | Enable/disable drag-and-drop |
AllowKeyboard | SfKanban | bool | true | Enable/disable keyboard navigation |
ConstraintType | SfKanban | ConstraintType? | null | WIP validation scope (Column/Swimlane) |
CssClass | SfKanban | string? | null | Custom CSS class for the board |
DataSource | SfKanban | IEnumerable<TValue>? | null | Local or remote data |
EnableRtl | SfKanban | bool | false | Right-to-left rendering |
EnableTooltip | SfKanban | bool | false | Show card tooltips on hover |
ExternalDropId | SfKanban | List<string>? | null | IDs of external drop targets |
Height | SfKanban | string? | "auto" | Component height |
ID | SfKanban | string? | null | Component identifier |
KeyField | SfKanban | string? | (required) | Field that maps cards to columns |
Locale | SfKanban | string? | "en-US" | Localization culture |
Query | SfKanban | Query? | null | Remote data filter/sort query |
HeaderField | KanbanCardSettings | string? | null | Card header data field |
ContentField | KanbanCardSettings | string? | null | Card body data field |
ShowHeader | KanbanCardSettings | bool? | true | Show/hide card headers |
KeyField | KanbanColumn | List<string> | (required) | Status values for this column |
HeaderText | KanbanColumn | string? | null | Column header display text |
MaxCount | KanbanColumn | int? | null | WIP maximum limit |
MinCount | KanbanColumn | int? | null | WIP minimum limit |
AllowToggle | KanbanColumn | bool | true | Expand/collapse column |
KeyField | KanbanSwimlaneSettings | string? | null | Swimlane grouping field |
ShowEmptySwimlane | KanbanSwimlaneSettings | bool | false | Show empty swimlane rows |
SortBy | KanbanSortSettings | SortOrderBy | DataSourceOrder | Card sort mode |
Field | KanbanSortSettings | string? | null | Field used for index/custom sort |
````
Responsive Mode in Blazor Kanban Component
The Kanban component automatically adapts to smaller screen sizes with a responsive layout designed for touch and mobile devices.
Table of Contents
Default Responsive Layout
On small screens (width ≤ 600px), the Kanban component renders in a responsive view by default:
- 80% width: The active/selected column occupies 80% of the screen
- 20% width: Adjacent columns appear at 20% as a peek
Users can swipe left or right to navigate between columns. The active column expands to full view.
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks">
<KanbanColumns>
<KanbanColumn HeaderText="Backlog" KeyField="@(new List<string>() {"Open"})"></KanbanColumn>
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() {"InProgress"})"></KanbanColumn>
<KanbanColumn HeaderText="Testing" KeyField="@(new List<string>() {"Testing"})"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() {"Close"})"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Id" ContentField="Summary"></KanbanCardSettings>
</SfKanban>No additional configuration is needed. The responsive layout activates automatically based on screen width.
Touch Interactions in Responsive Mode
| Interaction | Action |
|---|---|
| Tap and hold a card | Activates drag mode for the card |
| Swipe left/right | Navigate between columns |
| Tap a card | Select the card (single selection mode) |
Swimlane Responsive Layout
When swimlanes are enabled, the responsive mode shows a popup/dropdown to let users switch swimlane rows:
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks">
<KanbanColumns>
<KanbanColumn HeaderText="Backlog" KeyField="@(new List<string>() {"Open"})"></KanbanColumn>
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() {"InProgress"})"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() {"Close"})"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Id" ContentField="Summary"></KanbanCardSettings>
<KanbanSwimlaneSettings KeyField="Assignee" TextField="Assignee"></KanbanSwimlaneSettings>
</SfKanban>In swimlane responsive mode:
- A swimlane selector dropdown appears at the top
- The selected swimlane row's cards are shown in the active column view
- Users can swipe to navigate between columns while staying in the selected swimlane
Scrolling
In responsive mode, horizontal scrolling within columns is supported automatically. Content beyond the viewport is reachable by scrolling.
To enable vertical scrolling within columns, set a fixed height:
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks" Height="500px">
<KanbanColumns>
<KanbanColumn HeaderText="Backlog" KeyField="@(new List<string>() {"Open"})"></KanbanColumn>
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() {"InProgress"})"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() {"Close"})"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Id" ContentField="Summary"></KanbanCardSettings>
</SfKanban>Selection in Responsive Mode
In responsive mode, only single card selection is supported. Multi-selection via Ctrl+click or Shift+click is not available on touch devices:
<!-- Single selection is the effective mode on touch/mobile -->
<KanbanCardSettings HeaderField="Id" ContentField="Summary"
SelectionType="SelectionType.Single">
</KanbanCardSettings>Even if SelectionType.Multiple is configured, on touch devices only single selection is active.Responsive Behavior Summary
| Feature | Desktop | Mobile/Touch |
|---|---|---|
| Column layout | All columns visible | 80%/20% active column view |
| Card drag | Mouse drag | Tap and hold, then drag |
| Column navigation | Scroll bar | Swipe gesture |
| Swimlane navigation | Rows visible | Dropdown selector |
| Card selection | Single or Multiple | Single only |
| Keyboard navigation | Full support | Not applicable |
Sorting in Blazor Kanban Component
The Kanban component allows cards within each column to be sorted using KanbanSortSettings.
Table of Contents
Default Data Source Order
By default, cards render in the same order as the data source. This is SortBy.DataSourceOrder:
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks">
<KanbanColumns>
<KanbanColumn HeaderText="Backlog" KeyField="@(new List<string>() {"Open"})"></KanbanColumn>
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() {"InProgress"})"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() {"Close"})"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Id" ContentField="Summary"></KanbanCardSettings>
<KanbanSortSettings SortBy="SortOrderBy.DataSourceOrder" Direction="SortDirection.Ascending"></KanbanSortSettings>
</SfKanban>Sort by Index Field
Sort cards by a numeric index field. Map the index field with Field:
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks">
<KanbanColumns>
<KanbanColumn HeaderText="Backlog" KeyField="@(new List<string>() {"Open"})"></KanbanColumn>
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() {"InProgress"})"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() {"Close"})"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Id" ContentField="Summary"></KanbanCardSettings>
<KanbanSortSettings SortBy="SortOrderBy.Index" Field="RankId" Direction="SortDirection.Ascending"></KanbanSortSettings>
</SfKanban>
@code {
public class TasksModel
{
public string Id { get; set; }
public string Status { get; set; }
public string Summary { get; set; }
public int RankId { get; set; } // Index field for sorting
}
public List<TasksModel> Tasks = new List<TasksModel>()
{
new TasksModel { Id = "Task 1", Status = "Open", Summary = "Analyze requirements.", RankId = 1 },
new TasksModel { Id = "Task 2", Status = "Open", Summary = "Update website.", RankId = 2 },
new TasksModel { Id = "Task 3", Status = "InProgress", Summary = "Fix browser issues.", RankId = 1 },
};
}WhenSortBy="SortOrderBy.Index", drag-and-drop updates theRankIdvalues automatically to maintain the new order.
Custom Sort Order
Use SortOrderBy.Custom along with a custom comparer to implement your own sort logic:
<KanbanSortSettings SortBy="SortOrderBy.Custom" Field="Priority" Direction="SortDirection.Ascending"></KanbanSortSettings>When SortBy is Custom, the Field property specifies which field's values are compared. You can handle the SwimlaneSorting event or use custom data ordering in the data source.
Sort Direction
| Value | Description |
|---|---|
Ascending | Cards sorted in ascending order (default) |
Descending | Cards sorted in descending order |
<KanbanSortSettings SortBy="SortOrderBy.Index" Field="RankId" Direction="SortDirection.Descending"></KanbanSortSettings>KanbanSortSettings Properties
| Property | Type | Description |
|---|---|---|
SortBy | SortOrderBy | Sort method: DataSourceOrder, Index, Custom |
Field | string | Data source field used for sorting (required for Index and Custom) |
Direction | SortDirection | Sort order: Ascending or Descending |
SortOrderBy Enum Values
| Value | Description |
|---|---|
DataSourceOrder | Cards appear in the same order as the data source |
Index | Cards are sorted by a numeric rank/index field |
Custom | Cards are sorted using a user-defined field and custom logic |
Styling and Appearance in Blazor Kanban Component
Customize the Kanban component's appearance using CSS class overrides and built-in styling hooks.
Table of Contents
CSS Classes
The following CSS classes are available for customization:
| CSS Class | Description |
|---|---|
.e-kanban | Root element of the Kanban component |
.e-kanban-table | Kanban outer table element |
.e-header-row | Header row element |
.e-header-cells | Header cell elements |
.e-header-wrap | Header wrap element |
.e-header-title | Header title element |
.e-header-text | Header title text element |
.e-item-count | Item count display element in header |
.e-limits | Constraint (min/max) limits display |
.e-min-count | Minimum count constraint element |
.e-max-count | Maximum count constraint element |
.e-kanban-content | Content area (cards container) |
.e-content-row | Content row element |
.e-content-cells | Content cell elements |
.e-card-wrapper | Wrapper containing all cards in a cell |
.e-card-container | Container element for an individual card |
.e-card | Individual card element |
.e-card-header | Card header element |
.e-card-header-title | Card header title text |
.e-card-content | Card body content element |
.e-card-tags | Card tag wrapper element |
.e-card-tag-field | Individual card tag element |
.e-card-footer | Card footer element |
.e-card-footer-css | Individual footer CSS class element |
.e-card-left-border | Card left border (GrabberField color) |
.e-swimlane-row | Swimlane row element |
.e-swimlane-header | Swimlane header row |
.e-swimlane-text | Swimlane header text |
.e-swimlane-count | Card count in swimlane header |
.e-frozen-swimlane-row | Frozen swimlane row header |
.e-toggle-column | Collapsed/toggled column element |
.e-collapsed | Applied when a column is collapsed |
.e-empty-card | Empty placeholder card in an empty column |
.e-kanban-dialog | Built-in dialog element |
.e-kanban-form-wrapper | Dialog form wrapper |
.e-tooltip-wrap | Tooltip wrapper element |
Customizing Fixed Header
When a Kanban column header is fixed/sticky during scroll, customize it with:
.e-kanban .e-header-cells.e-fixed-header {
background-color: #e0e0e0;
font-weight: bold;
}Common Customization Examples
Card Background Color by Priority
.e-kanban .e-card[data-priority="Critical"] {
background-color: #ffe0e0;
border-left: 4px solid #ff4444;
}
.e-kanban .e-card[data-priority="Low"] {
background-color: #e0ffe0;
border-left: 4px solid #44aa44;
}Column Header Background
.e-kanban .e-header-cells {
background-color: #1e88e5;
color: white;
}Card Hover Effect
.e-kanban .e-card:hover {
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
transform: translateY(-2px);
transition: all 0.2s ease;
}Swimlane Header Styling
.e-kanban .e-swimlane-row .e-swimlane-header {
background-color: #f5f5f5;
border-bottom: 2px solid #1e88e5;
padding: 8px 12px;
}
.e-kanban .e-swimlane-row .e-swimlane-text {
font-size: 14px;
font-weight: 600;
color: #333;
}Constraint Limit Indicators
/* Warning when approaching maximum */
.e-kanban .e-limits.e-max-count {
color: #ff6f00;
font-weight: bold;
}
/* Error when below minimum */
.e-kanban .e-limits.e-min-count {
color: #d32f2f;
font-weight: bold;
}Using CssClass Property
Apply a custom CSS class to the Kanban for scoped styling:
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks" CssClass="custom-kanban">
...
</SfKanban>
<style>
.custom-kanban .e-header-cells {
background-color: #673ab7;
color: white;
}
.custom-kanban .e-card {
border-radius: 8px;
}
</style>Tooltip in Blazor Kanban Component
The Kanban component provides built-in tooltip support to display additional card details on hover.
Table of Contents
Enabling Tooltip
Enable the tooltip with EnableTooltip="true" on SfKanban. The tooltip shows the card's header and content fields by default:
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks" EnableTooltip="true">
<KanbanColumns>
<KanbanColumn HeaderText="Backlog" KeyField="@(new List<string>() {"Open"})"></KanbanColumn>
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() {"InProgress"})"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() {"Close"})"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Id" ContentField="Summary"></KanbanCardSettings>
</SfKanban>
@code {
public class TasksModel
{
public string Id { get; set; }
public string Status { get; set; }
public string Summary { get; set; }
}
public List<TasksModel> Tasks = new List<TasksModel>()
{
new TasksModel { Id = "Task 1", Status = "Open", Summary = "Analyze the new requirements gathered from the customer." },
new TasksModel { Id = "Task 2", Status = "InProgress", Summary = "Improve application performance." },
new TasksModel { Id = "Task 3", Status = "Open", Summary = "Arrange a web meeting with the customer." },
new TasksModel { Id = "Task 4", Status = "InProgress", Summary = "Fix the issues reported in the IE browser." },
new TasksModel { Id = "Task 5", Status = "Close", Summary = "Validate new requirements." },
};
}Custom Tooltip Content
Add custom HTML elements to the card and apply the e-tooltip-text CSS class to include them in the tooltip:
<SfKanban TValue="TasksModel" KeyField="Status" DataSource="Tasks" EnableTooltip="true">
<KanbanColumns>
<KanbanColumn HeaderText="Backlog" KeyField="@(new List<string>() {"Open"})"></KanbanColumn>
<KanbanColumn HeaderText="In Progress" KeyField="@(new List<string>() {"InProgress"})"></KanbanColumn>
<KanbanColumn HeaderText="Done" KeyField="@(new List<string>() {"Close"})"></KanbanColumn>
</KanbanColumns>
<KanbanCardSettings HeaderField="Id" ContentField="Summary">
<Template>
@{
TasksModel data = (TasksModel)context;
<div class="e-card-content">
<p>@data.Summary</p>
<!-- This element's content will appear in the tooltip -->
<div class="e-tooltip-text">
<p>Assignee: @data.Assignee</p>
<p>Priority: @data.Priority</p>
<p>Type: @data.Type</p>
</div>
</div>
}
</Template>
</KanbanCardSettings>
</SfKanban>
@code {
public class TasksModel
{
public string Id { get; set; }
public string Status { get; set; }
public string Summary { get; set; }
public string Assignee { get; set; }
public string Priority { get; set; }
public string Type { get; set; }
}
}Elements with the e-tooltip-text CSS class are hidden on the card but are displayed in the tooltip popup when hovering over the card.Tooltip Properties Reference
| Property | Type | Description |
|---|---|---|
EnableTooltip | bool | Enable/disable the built-in tooltip (default: false) |
CSS Class for Custom Tooltip Content
| Class | Description |
|---|---|
e-tooltip-text | Applied to elements that should be visible in the tooltip but hidden on the card |