Skip to content

Commit

Permalink
Merge pull request #124 from artem-mangilev/fix-creating-connections
Browse files Browse the repository at this point in the history
fix: fix floating problem with manual edge creation
  • Loading branch information
artem-mangilev authored Jan 18, 2025
2 parents 81a76bf + 3fcdf29 commit 103fe96
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,13 @@ export class NodeComponent implements OnInit, AfterViewInit, OnDestroy, WithInje
private flowSettingsService = inject(FlowSettingsService);
private selectionService = inject(SelectionService);
private hostRef = inject<ElementRef<SVGElement>>(ElementRef);
private connectionController = inject(ConnectionControllerDirective);
private nodeAccessor = inject(NodeAccessorService);
private overlaysService = inject(OverlaysService);
private zone = inject(NgZone);

// TODO remove dependency from this directive
private connectionController = inject(ConnectionControllerDirective, { optional: true });

public nodeModel = input.required<NodeModel>();

public nodeTemplate = input<TemplateRef<any>>();
Expand Down Expand Up @@ -159,19 +161,19 @@ export class NodeComponent implements OnInit, AfterViewInit, OnDestroy, WithInje
// ignore drag by stopping propagation
event.stopPropagation();

this.connectionController.startConnection(handle);
this.connectionController?.startConnection(handle);
}

protected validateConnection(handle: HandleModel) {
this.connectionController.validateConnection(handle);
this.connectionController?.validateConnection(handle);
}

protected resetValidateConnection(targetHandle: HandleModel) {
this.connectionController.resetValidateConnection(targetHandle);
this.connectionController?.resetValidateConnection(targetHandle);
}

protected endConnection() {
this.connectionController.endConnection();
this.connectionController?.endConnection();
}

protected pullNode() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import { skip } from 'rxjs';
import { Point } from '../../interfaces/point.interface';
import { ViewportState } from '../../interfaces/viewport.interface';
import { FlowStatusService } from '../../services/flow-status.service';
import { ConnectionControllerDirective } from '../../directives/connection-controller.directive';
import { FlowEntitiesService } from '../../services/flow-entities.service';
import { ConnectionSettings } from '../../interfaces/connection-settings.interface';
import { ConnectionModel } from '../../models/connection.model';
Expand Down Expand Up @@ -64,11 +63,6 @@ import { RootPointerDirective } from '../../directives/root-pointer.directive';
import { RootSvgContextDirective } from '../../directives/root-svg-context.directive';
import { RootSvgReferenceDirective } from '../../directives/reference.directive';

const connectionControllerHostDirective = {
directive: ConnectionControllerDirective,
outputs: ['onConnect'],
};

const changesControllerHostDirective = {
directive: ChangesControllerDirective,
outputs: [
Expand Down Expand Up @@ -124,7 +118,7 @@ const changesControllerHostDirective = {
KeyboardService,
OverlaysService,
],
hostDirectives: [connectionControllerHostDirective, changesControllerHostDirective],
hostDirectives: [changesControllerHostDirective],
imports: [
RootSvgReferenceDirective,
RootSvgContextDirective,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
import { Directive, computed, effect, inject, output } from '@angular/core';
import { Directive, computed, inject } from '@angular/core';
import { Connection } from '../interfaces/connection.interface';
import { FlowStatusService, batchStatusChanges } from '../services/flow-status.service';
import { FlowStatusConnectionEnd, FlowStatusService } from '../services/flow-status.service';

import { FlowEntitiesService } from '../services/flow-entities.service';
import { HandleModel } from '../models/handle.model';
import { adjustDirection } from '../utils/adjust-direction';
import { outputFromObservable, toObservable } from '@angular/core/rxjs-interop';
import { filter, map, tap } from 'rxjs';

@Directive({
selector: '[connectionController]',
selector: '[onConnect]',
standalone: true,
})
export class ConnectionControllerDirective {
private statusService = inject(FlowStatusService);
private flowEntitiesService = inject(FlowEntitiesService);

/**
* This event fires when user tries to create new Edge.
*
Expand All @@ -22,16 +27,10 @@ export class ConnectionControllerDirective {
* @todo add connect event and deprecate onConnect
*/
// eslint-disable-next-line @angular-eslint/no-output-on-prefix
public readonly onConnect = output<Connection>();

private statusService = inject(FlowStatusService);
private flowEntitiesService = inject(FlowEntitiesService);

protected connectEffect = effect(
() => {
const status = this.statusService.status();

if (status.state === 'connection-end') {
public readonly onConnect = outputFromObservable<Connection>(
toObservable(this.statusService.status).pipe(
filter((status): status is FlowStatusConnectionEnd => status.state === 'connection-end'),
map((status) => {
let source = status.payload.source;
let target = status.payload.target;
let sourceHandle = status.payload.sourceHandle;
Expand All @@ -57,20 +56,16 @@ export class ConnectionControllerDirective {
const sourceHandleId = sourceHandle.rawHandle.id;
const targetHandleId = targetHandle.rawHandle.id;

const connectionModel = this.flowEntitiesService.connection();
const connection = {
return {
source: sourceId,
target: targetId,
sourceHandle: sourceHandleId,
targetHandle: targetHandleId,
};

if (connectionModel.validator(connection)) {
this.onConnect.emit(connection);
}
}
},
{ allowSignalWrites: true },
}),
tap(() => this.statusService.setIdleStatus()),
filter((connection) => this.flowEntitiesService.connection().validator(connection)),
),
);

protected isStrictMode = computed(() => this.flowEntitiesService.connection().mode === 'strict');
Expand Down Expand Up @@ -145,12 +140,7 @@ export class ConnectionControllerDirective {
const target = status.payload.target;
const targetHandle = status.payload.targetHandle;

batchStatusChanges(
// call to create connection
() => this.statusService.setConnectionEndStatus(source!, target!, sourceHandle!, targetHandle!),
// when connection created, we need go back to idle status
() => this.statusService.setIdleStatus(),
);
this.statusService.setConnectionEndStatus(source, target, sourceHandle, targetHandle);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,3 @@ export class FlowStatusService {
this.status.set({ state: 'connection-end', payload: { source, target, sourceHandle, targetHandle } });
}
}

/**
* Batch status changes together to call them one after another
*
* @param changes list of set[FlowStatus.state]Status() calls
*/
export function batchStatusChanges(...changes: (() => void)[]) {
if (changes.length) {
const [firstChange, ...restChanges] = changes;
// first change is sync
firstChange();
// without timer, subscribed effects/comuted signals only get latest value
restChanges.forEach((change) => setTimeout(() => change()));
}
}
2 changes: 2 additions & 0 deletions projects/ngx-vflow-lib/src/lib/vflow/vflow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { MiniMapComponent } from './public-components/minimap/minimap.component'
import { NodeToolbarComponent } from './public-components/node-toolbar/node-toolbar.component';
import { ResizableComponent } from './public-components/resizable/resizable.component';
import { HandleComponent } from './public-components/handle/handle.component';
import { ConnectionControllerDirective } from './directives/connection-controller.directive';

export const Vflow = [
VflowComponent,
Expand All @@ -22,6 +23,7 @@ export const Vflow = [
MiniMapComponent,
NodeToolbarComponent,
DragHandleDirective,
ConnectionControllerDirective,

NodeHtmlTemplateDirective,
GroupNodeTemplateDirective,
Expand Down

0 comments on commit 103fe96

Please sign in to comment.