Installation:
composer require getartisanflow/wireflow
php artisan wireflow:install
First Component:
Create a Livewire component with WithWireFlow concern:
use ArtisanFlow\WireFlow\Concerns\WithWireFlow;
class FlowEditor extends Component
{
use WithWireFlow;
public array $nodes = [
['id' => '1', 'position' => ['x' => 100, 'y' => 100], 'data' => ['label' => 'Start']],
];
public array $edges = [];
}
Blade Integration:
<x-flow wire:model="nodes" wire:model:edges="edges">
<x-slot:node>
<div x-flow-handle:target.top></div>
<span x-text="node.data.label"></span>
</x-slot:node>
</x-flow>
$nodes and $edges in your Livewire component.<x-flow> with wire:model bindings.:node slot.x-flow-handle) for edge connections.Livewire Model Binding:
Use wire:model for reactive updates:
<x-flow wire:model="nodes" wire:model:edges="edges">
$nodes and $edges arrays.Custom Node Data: Extend node data structure for rich content:
$nodes = [
[
'id' => '1',
'position' => ['x' => 100, 'y' => 100],
'data' => [
'label' => 'Process',
'type' => 'process',
'color' => '#4CAF50',
],
],
];
Access via node.data in Blade slots.
Panels and Toolbars:
<x-flow-panel>
<x-slot name="title">Node Properties</x-slot>
<input wire:model="selectedNode.data.label">
</x-flow-panel>
<x-flow-toolbar>
<button wire:click="addNode">Add Node</button>
</x-flow-toolbar>
Drag-and-Drop Handles:
<x-flow-handle:target.top class="bg-blue-500"></x-flow-handle>
<x-flow-handle:source.bottom class="bg-green-500"></x-flow-handle>
Event Handling: Use Livewire hooks for flow events:
protected $listeners = ['nodeCreated' => 'handleNodeCreated'];
public function handleNodeCreated($node) {
// Save to DB or trigger side effects
}
Validation: Validate node/edge data before saving:
protected function rules() {
return [
'nodes.*.data.label' => 'required|string',
'edges.*.source' => 'required|exists:nodes,id',
'edges.*.target' => 'required|exists:nodes,id',
];
}
Edge Connection Issues:
source and target IDs in $edges match node IDs.x-flow-handle directives are placed inside <x-slot:node>.Livewire Sync Delays:
wire:ignore on non-critical elements:
<div wire:ignore>...</div>
Default Styling: Override AlpineFlow defaults via published config:
php artisan vendor:publish --provider="ArtisanFlow\WireFlow\WireFlowServiceProvider"
Customize in config/wireflow.php (e.g., handle_size, node_padding).
Slot Scope:
node and edge are available in slots, but flow scope is not exposed by default. Use AlpineFlow’s x-flow directives for global flow data.Custom Node Types:
Extend functionality via AlpineFlow’s x-flow-node directive:
<x-flow>
<x-slot:node>
@if($node->data->type === 'decision')
<div x-flow-node:decision>
<!-- Custom decision node template -->
</div>
@else
<div x-flow-node:default>
<span x-text="node.data.label"></span>
</div>
@endif
</x-slot:node>
</x-flow>
Server-Side Validation:
Use Livewire’s updatedNodes/updatedEdges to validate changes before persistence:
public function updatedNodes($value) {
$this->validate([
'nodes.*.data.label' => 'required|unique:nodes,name,' . $value[0]['id'] ?? null,
]);
}
Performance:
public function getNodesProperty() {
return Node::query()
->whereIn('id', $this->visibleNodeIds)
->get();
}
How can I help you explore Laravel packages today?