Complete guide for using VIOVNL.Flowy.Blazor - an interactive hierarchical tree visualization component for Blazor applications.
In your _Imports.razor:
@using VIOVNL.Flowy.Blazor.Components
@using VIOVNL.Flowy.Blazor.ModelsIn your App.razor or layout file (<head> section):
<link href="_content/VIOVNL.Flowy.Blazor/css/flowy.css" rel="stylesheet" />Note: JavaScript is loaded automatically via ES6 modules.
@page "/tree"
@rendermode InteractiveServer
<div style="display: flex; height: 600px; gap: 16px;">
<FlowyComponentsPanel Components="@components"
Title="Components"
Style="width: 220px;" />
<FlowyCanvasEditor Components="@components"
Style="flex: 1;" />
</div>
@code {
private List<FlowyComponentItem> components = new()
{
new FlowyComponentItem
{
ComponentId = "person",
Name = "Person",
Color = "#667eea"
},
new FlowyComponentItem
{
ComponentId = "spouse",
Name = "Spouse",
Color = "#f093fb"
}
};
}Use Blazor RenderFragment for rich, customizable node content:
@code {
private List<FlowyComponentItem> components = new()
{
new FlowyComponentItem
{
ComponentId = "executive",
Name = "Executive",
Color = "#667eea",
BodyContent = @<div style="display: flex; align-items: center; gap: 8px;">
<span style="font-size: 20px;">👔</span>
<div>
<div style="font-weight: 700;">Executive</div>
<div style="font-size: 11px; opacity: 0.8;">Leadership</div>
</div>
</div>
}
};
}Access component methods via @ref:
<FlowyCanvasEditor @ref="canvasEditor" Components="@components" />
@code {
private FlowyCanvasEditor? canvasEditor;
// Add node programmatically
private async Task AddNode()
{
var node = await canvasEditor!.AddNodeAsync(
"New Node",
"person",
"#667eea",
parentId: null
);
}
// Zoom controls
private async Task ZoomIn() => await canvasEditor!.ZoomInAsync();
private async Task FitScreen() => await canvasEditor!.FitAllNodesInViewportAsync();
// Navigation
private async Task FocusNode(Guid nodeId)
=> await canvasEditor!.FocusItemAsync(nodeId);
}Comprehensive event system for tracking user interactions:
<FlowyCanvasEditor
Components="@components"
OnNodeDropped="HandleNodeDropped"
OnNodeMoved="HandleNodeMoved"
OnNodeRemoved="HandleNodeRemoved"
OnNodeSelected="HandleNodeSelected"
OnValidateDropTarget="HandleValidation" />
@code {
private Task HandleNodeDropped(FlowyNodeDroppedEventArgs args)
{
Console.WriteLine($"Node '{args.Node.Name}' dropped on {args.TargetNode?.Name ?? "canvas"}");
return Task.CompletedTask;
}
private Task HandleValidation(FlowyValidationEventArgs args)
{
// Custom validation logic
if (args.TargetNode?.ComponentId == "restricted" && args.Node.ComponentId == "forbidden")
{
args.IsValid = false;
args.ValidationMessage = "This combination is not allowed!";
}
return Task.CompletedTask;
}
}Save and restore tree structures:
@code {
private async Task ExportTree()
{
var json = canvasEditor!.ExportJson();
await File.WriteAllTextAsync("tree.json", json);
}
private async Task ImportTree()
{
var json = await File.ReadAllTextAsync("tree.json");
await canvasEditor!.ImportJson(json);
}
}| Parameter | Type | Default | Description |
|---|---|---|---|
Components |
List<FlowyComponentItem> |
[] |
Available draggable components |
EnablePanning |
bool |
true |
Allow canvas panning |
AutoZoom |
bool |
false |
Auto-fit all nodes (two-way bindable) |
AutoCenter |
bool |
false |
Auto-center on root node |
ZoomLevel |
double |
1.0 |
Manual zoom (0.1-3.0, two-way bindable) |
Smooth |
bool |
true |
Enable smooth animations with momentum |
EnableDragDrop |
bool |
true |
Enable drag & drop functionality |
Debug |
bool |
false |
Enable console logging |
<FlowyCanvasEditor
@bind-ZoomLevel="zoomLevel"
@bind-AutoZoom="autoZoom" />
@code {
private double zoomLevel = 1.0;
private bool autoZoom = true;
}AddNodeAsync(name, componentId, color, parentId, isDraggable, canHaveChildren)- Add nodeRemoveNodeAsync(nodeId)- Remove node and descendantsMoveNodeAsync(nodeId, newParentId, position)- Move nodeResetAsync()- Clear all nodes
GetNodeById(nodeId)- Get specific nodeGetChildren(parentNode)- Get child nodesGetRootNode()- Get root nodeNodes- Read-only collection of all nodes
ZoomInAsync(),ZoomOutAsync(),ZoomResetAsync()SetZoomLevelAsync(level)- Set specific zoomFitAllNodesInViewportAsync()- Fit all nodesCenterAsync()- Center on rootFocusItemAsync(nodeId)- Focus specific node
FlowDropletsAsync(startNodeId, endNodeId, duration, count, delay, distance, easing)- Animate dropletsSetNodeDraggableAsync(nodeId, draggable)- Lock/unlock nodeSetNodeCanHaveChildrenAsync(nodeId, canHave)- Control child acceptanceExportJson(),ImportJson(json)- Serialization