In the previous article, we built a basic editor with two nodes and a single connection. In this part, we move toward a real Angular node editor by adding custom node components, interactive connectors, and a reusable node palette.
It’s not a full low-code platform just yet, but it establishes the custom-node architecture most teams need before layering on validation, side panels, and richer workflow behavior.

Version note: The linked repository preserves the original v18 implementation. The examples below use the unified connector and event APIs introduced in v19.
Our visual flow will be based on three main components:
We’ll continue building on the project from the previous article.
First, we need to load the required fonts and icons. Add the following to your index.html:
Then, reset default styles and apply the base font by adding this to your styles.scss:
Let’s begin by defining the models for nodes and connections. Below are the TypeScript interfaces and an example set of 8 node types, which you can expand or customize later as needed:
Now let’s define a list of available nodes:
Next, we’ll create the flow-palette component — a vertical sidebar from which we can drag nodes into the canvas.
Each palette item is a div using the fExternalItem directive, which enables external drag-and-drop support with Foblex Flow.
We use ::ng-deep here because drag preview elements are appended to the document.body. Without it, styles wouldn’t apply to them.
Now we can add nodes from the palette directly into the flow by handling the following event:
Each node in the editor will be represented by a dedicated Angular component:
Each node has target and source ports built with the unified fConnector directive. fConnectorType defines each port’s role, while fConnectorId gives the connection model a stable endpoint.
While we could have kept the connector inline inside the node, we’re moving it to a standalone component for better style encapsulation and code separation.
Up to this point, we’ve been rendering nodes manually — statically defined in the template. Now it’s time to take the next step: we’ll enable users to dynamically add nodes by dragging them from the side palette into the canvas.
Here’s how the flow works:
We start by creating a signal to hold the list of all current nodes:
Signals make the UI reactive — whenever the list updates, the DOM reflects the changes.
Now let’s define the method that will run when a new node is added:
Here’s what’s happening:
event.data.generateGuid().event.externalItemRect for the dropped item’s position in flow coordinates.event.targetContainerId identifies the node or group under the drop, when present.event.dropPosition provides the exact pointer position when custom placement logic needs it.Let’s replace the static nodes with a dynamic list rendered using @for:
Key notes:
When a user drags a node from flow-palette, the fExternalItem directive fires an fCreateNode event. We handle that event in the createNode method, construct a new node object, and append it to the list. Thanks to @for, the UI instantly reflects the change.
To ensure each node has a unique identifier, we use a small utility function:
Now that we can add nodes from the palette, it’s time to implement the next key step: connecting nodes together — and rendering those connections inside the canvas.
This component goes inside <f-canvas> and renders a temporary line when the user starts dragging a connection from an output. It also triggers the fCreateConnection event once the drag ends — either over a valid input or in empty space.
Let’s update our Flow component template to handle the connection event and also render all created connections:
Here’s the method that handles fCreateConnection and stores the connection in a reactive signal:
Here’s what’s happening:
event.sourceId is the ID of the source connector the user dragged from.event.targetId is the target connector ID, or undefined when the pointer is released in empty space.event.dropPosition is the pointer position in flow coordinates and can be used to open a node picker or apply custom drop behavior.Now we have a complete cycle in place:
At this stage, our visual editor is starting to look much more like a real low-code platform. We’ve learned how to:
The key idea in this part is the separation of logic from visual behavior. This implementation uses Foblex Flow's default stateless mode: the library tells you what happened when a node is added, a connection starts, or a drag completes, and the application updates its own signals.
For editors that do not need a separate application store, the optional Managed Flow State plugin can hold typed graph records and apply supported gestures automatically. It does not change the manual event-driven approach shown in this series.
In the next part, we’ll focus on styling and connection behavior. We’ll add curved lines, color schemes, arrows, custom states, and interactions like hover, click, and delete. These enhancements will give your flow editor a polished and professional feel.
If you like the project — leave a ⭐ on GitHub, join the discussions, and share your feedback!