DEV Community

Cover image for Building AI Low-Code Platform in Angular — Part 4: Styling and Handling Connections
Siarhei Huzarevich
Siarhei Huzarevich

Posted on • Edited on • Originally published at Medium

Building AI Low-Code Platform in Angular — Part 4: Styling and Handling Connections

Updated for Foblex Flow v19.1.6 (July 2026). Connection examples now use fSourceId / fTargetId, and reassignment uses the preferred v19 event fields.

In the previous part, we brought our node editor to life with custom components and a dynamic palette. But nodes alone don’t make the magic — the real power comes from how they connect. And more importantly, how those connections behave, look, and respond to users.

Today, we’re upgrading our flow with some serious UX polish:

  • 🔁 Enable dynamic reattachment of connections (drag to reconnect!)
  • 🏁 Style connections with sleek SVG markers
  • ✨ Add hover highlights and interactivity

Let’s turn static lines into smart, responsive connectors — and give our low-code UI a professional edge.

🔧 Historical tutorial source — Foblex Flow 17.6.0

🔧 Explore the full application

The linked tutorial repository is the historical 17.6.0 implementation. The snippets below are updated for 19.1.6. For maintained v19 code, use the AI Low-Code Platform example.

🔁 Reattaching Connections

Connections in Foblex Flow aren’t just static wires — they’re fully interactive and reconfigurable. Each end of a connection features a drag handle — an invisible area you can grab to change where the connection starts or ends.

Connection Target Reassignable

By default, only the target end (target connector) is draggable. But you can also make the source end (source connector) reassignable by setting the fReassignableStart=”true” input. This gives you precise control over which ends can be modified — on a per-connection basis.

Both sides reassignable

Want to rewire a connection? Drag one endpoint and drop it onto another connector. When the gesture finishes, fDraggable on <f-flow> emits fReassignConnection:

<f-flow fDraggable
        (fCreateNode)="createNode($event)"
        (fCreateConnection)="createConnection($event)"
        (fReassignConnection)="reassignConnection($event)">
</f-flow>
Enter fullscreen mode Exit fullscreen mode

This event contains everything you need to handle the reattachment:

class FReassignConnectionEvent {
  connectionId: string;
  endpoint: 'source' | 'target';
  previousSourceId: string;
  nextSourceId: string | undefined;
  previousTargetId: string;
  nextTargetId: string | undefined;
  dropPosition: IPoint;
}
Enter fullscreen mode Exit fullscreen mode

🧠 Tip:

The event still fires if the user releases the endpoint without a compatible connector. In that case, nextTargetId or nextSourceId is undefined, while dropPosition contains the flow coordinates where the pointer was released.

This is extremely useful if you want to open a context menu or create a new node on the fly at that position.

Here’s how to update your connection list when the target changes:

protected reassignConnection(event: FReassignConnectionEvent): void {
  if (event.endpoint !== 'target' || !event.nextTargetId) {
    return;
  }

  const nextTargetId = event.nextTargetId;
  this.connections.update((connections) =>
    connections.map((connection) =>
      connection.id === event.connectionId
        ? { ...connection, to: nextTargetId }
        : connection
    )
  );
}
Enter fullscreen mode Exit fullscreen mode

That’s it — your users can now interactively rewire the flow by grabbing connection ends and reattaching them wherever they need. It’s a small feature, but it makes the editor feel dynamic, intuitive, and alive.

https://flow.foblex.com/examples/drag-to-reassign

🧬 Connection Types and Behaviors

Connections in Foblex Flow aren’t just visual lines — they’re deeply customizable and behave exactly how you want them to.

Let’s start with the four connection types, each offering a different visual style:

  • straight — a simple straight line
  • segment — a segmented line with right angles (ideal for logic-style editors)
  • bezier — a smooth, curved Bézier path
  • adaptive-curve — a curve that adapts to the relative connector positions

Connection types

https://flow.foblex.com/examples/connection-types

Next, you can define how the connection behaves when linking nodes:

  • fixed — connects from a specific side (left, right, top, bottom) defined via fConnectorConnectableSide
  • fixed_center — connects from the exact center of each node
  • floating — auto-calculates the intersection between the node’s shape and the imaginary line between node centers (great for circular or irregular shapes)

Connection behaviors

https://flow.foblex.com/examples/connection-behaviours

These options give you total control over both aesthetics and logic — whether you’re building a chatbot flow, a wiring diagram, or an AI pipeline.

📖 Want to dive deeper into all behaviors and visuals?

👉 Read the full documentation

In our low-code platform, we’ll use a Bézier curve with a fixed side behavior, which feels natural for horizontal flow layouts:

<f-connection [fConnectionId]="connection.id"
              fBehavior="fixed"
              fType="bezier"
              [fSourceId]="connection.from"
              [fTargetId]="connection.to" />
Enter fullscreen mode Exit fullscreen mode

You’re now in control — not just of where your connections go, but how they feel when they get there.

🏁 Adding SVG Markers to Connections

A great UI isn’t just about layout — it’s about clarity and direction. When working with connections, nothing communicates intent better than directional markers.

With Foblex Flow, you can attach custom SVG markers to the start or end of any connection. These can be arrows, dots, diamonds — anything you can draw in SVG.

Connection markers

https://flow.foblex.com/examples/connection-markers

Here’s a minimal example that adds a simple circle to the start of a connection:

<f-connection [fSourceId]="id1" [fTargetId]="id2">
  <svg fMarker type="f-connection-marker-start"
       [height]="10" [width]="10" [refX]="5" [refY]="5">
    <circle cx="5" cy="5" r="2" fill="var(--connection-color)" />
  </svg>
</f-connection>
Enter fullscreen mode Exit fullscreen mode

📌 fMarker input parameters:

  • type — the marker type
  • width, height — size of the marker viewport
  • refX, refY — anchoring point (where the marker attaches to the connection)

All marker types are defined in the EFMarkerType enum:

enum EFMarkerType {
  START,
  END,
  SELECTED_START,
  SELECTED_END,
  START_ALL_STATES,
  END_ALL_STATES,
}
Enter fullscreen mode Exit fullscreen mode

Use START / END with SELECTED_START / SELECTED_END when selected markers need separate styling. START_ALL_STATES and END_ALL_STATES create both normal and selected markers from one declaration.

Here’s a full example that applies all four types of markers on a connection:

protected readonly eMarkerType = EFMarkerType;
Enter fullscreen mode Exit fullscreen mode
<f-connection [fConnectionId]="connection.id"
              fBehavior="fixed"
              fType="bezier"
              [fSourceId]="connection.from"
              [fTargetId]="connection.to">
  <svg viewBox="0 0 10 10" fMarker [type]="eMarkerType.START" [height]="10" [width]="10" [refX]="5" [refY]="5">
    <circle cx="5" cy="5" r="2" fill="var(--connection-color)" />
  </svg>
  <svg viewBox="0 0 700 700" fMarker [type]="eMarkerType.END" [height]="5" [width]="5" [refX]="4" [refY]="2.5">
    <path fill="var(--connection-color)" d="M0,0L700,350L0,700L150,350z" />
  </svg>
  <svg viewBox="0 0 10 10" fMarker [type]="eMarkerType.SELECTED_START" [height]="10" [width]="10" [refX]="5" [refY]="5">
    <circle cx="5" cy="5" r="2" fill="var(--connection-color)" />
  </svg>
  <svg viewBox="0 0 700 700" fMarker [type]="eMarkerType.SELECTED_END" [height]="5" [width]="5" [refX]="4" [refY]="2.5">
    <path fill="var(--connection-color)" d="M0,0L700,350L0,700L150,350z" />
  </svg>
</f-connection>
Enter fullscreen mode Exit fullscreen mode

With just a few lines of SVG, your connections can now clearly show direction, communicate selection, and make the entire UI feel more polished and understandable.

Next, we’ll make them glow ✨

🎨 Styling Connections and Markers

Let’s make our connections not just smart — but stylish.

First, we’ll define a custom CSS variable — connection-color and apply it to both the stroke of the connection path and the fill of any SVG markers. This way, all visual elements stay perfectly in sync.

::ng-deep {
  .f-connection {
    --connection-color: rgba(60, 60, 67); // default line color

    &.f-selected {
      --connection-color: #3451b2; // highlighted color on selection
    }

    .f-connection-drag-handle {
      fill: transparent; // invisible grab area for reattachment
    }

    .f-connection-selection {
      stroke-width: 10; // makes the selection area easier to hit
    }

    .f-connection-path {
      stroke: var(--connection-color); // applies the CSS variable
      stroke-width: 2;
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

💡 Why use CSS variables?

They allow you to easily switch themes, support dark/light mode, or dynamically update styles on interaction — without touching the DOM.

👆 Hover Effect

Now let’s make our connections respond to user interaction. A subtle glow on hover helps users understand that a line is clickable or draggable.

.f-connection-selection {
  stroke-width: 15;

  &:hover {
    stroke: rgba(52, 81, 178, 0.1);
  }
}
Enter fullscreen mode Exit fullscreen mode

Just like that, your editor starts to feel alive — reacting to user input in a smooth, intuitive way.

✅ Done!

At this point, your connections are no longer just lines between nodes — they’re fully interactive, visually expressive, and ready for production use.

Here’s what we’ve achieved in this part:

✅ Enabled reattachment of connections with intuitive drag handles

✅ Supported reconnection from either side of the link

✅ Styled connection paths using CSS variables for easy theming

✅ Added SVG markers to visualize direction and selection

✅ Enhanced the UX with hover effects and visual feedback

Together, these improvements make a massive difference in how your flow editor feels to the user. Small touches like directional arrows or soft highlights can turn a technical tool into a truly enjoyable experience.

But we’re not stopping here.

Up next, we’ll take interactivity to the next level by adding a side panel that appears when a node is selected. This panel will allow users to:

  • View and edit node parameters dynamically
  • Bind controls to schema-driven forms
  • See changes reflected live in the flow

This is a huge step toward building a real low-code platform, where users don’t just connect logic — they configure and control it through a seamless UI.

Top comments (0)