diff --git a/packages/ng-diagram/projects/ng-diagram/src/lib/components/diagram/ng-diagram.component.spec.ts b/packages/ng-diagram/projects/ng-diagram/src/lib/components/diagram/ng-diagram.component.spec.ts index 102aa8783..a7680faa5 100644 --- a/packages/ng-diagram/projects/ng-diagram/src/lib/components/diagram/ng-diagram.component.spec.ts +++ b/packages/ng-diagram/projects/ng-diagram/src/lib/components/diagram/ng-diagram.component.spec.ts @@ -1,6 +1,6 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { Middleware, ModelAdapter } from '../../../core/src'; import { beforeEach, describe, expect, it, vi } from 'vitest'; +import { Middleware, ModelAdapter } from '../../../core/src'; import { FlowCoreProviderService, @@ -10,6 +10,7 @@ import { } from '../../services'; import { CursorPositionTrackerService } from '../../services/cursor-position-tracker/cursor-position-tracker.service'; import { InputEventsRouterService } from '../../services/input-events/input-events-router.service'; +import { TemplateProviderService } from '../../services/template-provider/template-provider.service'; import { NgDiagramComponent } from './ng-diagram.component'; describe('AngularAdapterDiagramComponent', () => { @@ -72,6 +73,9 @@ describe('AngularAdapterDiagramComponent', () => { setEnabled: vi.fn(), hasListeners: vi.fn(), }, + config: { + debugMode: false, + }, }), isInitialized: vi.fn().mockReturnValue(true), }, @@ -83,6 +87,7 @@ describe('AngularAdapterDiagramComponent', () => { onDragStartFromPalette: vi.fn(), }, }, + TemplateProviderService, CursorPositionTrackerService, InputEventsRouterService, ], @@ -148,6 +153,7 @@ describe('AngularAdapterDiagramComponent', () => { const templateMap = new Map([['test-type', mockTemplate]]); fixture.componentRef.setInput('nodeTemplateMap', templateMap); + fixture.detectChanges(); expect(component.getNodeTemplate('test-type')).toBe(mockTemplate); }); @@ -167,6 +173,7 @@ describe('AngularAdapterDiagramComponent', () => { const templateMap = new Map([['test-type', mockTemplate]]); fixture.componentRef.setInput('edgeTemplateMap', templateMap); + fixture.detectChanges(); expect(component.getEdgeTemplate('test-type')).toBe(mockTemplate); }); diff --git a/packages/ng-diagram/projects/ng-diagram/src/lib/components/diagram/ng-diagram.component.ts b/packages/ng-diagram/projects/ng-diagram/src/lib/components/diagram/ng-diagram.component.ts index 319450f79..d11f74808 100644 --- a/packages/ng-diagram/projects/ng-diagram/src/lib/components/diagram/ng-diagram.component.ts +++ b/packages/ng-diagram/projects/ng-diagram/src/lib/components/diagram/ng-diagram.component.ts @@ -32,6 +32,7 @@ import { ZoomingPointerDirective } from '../../directives/input-events/zooming/z import { ZoomingWheelDirective } from '../../directives/input-events/zooming/zooming-wheel.directive'; import { NgDiagramServicesAvailabilityCheckerDirective } from '../../directives/services-availability-checker/ng-diagram-services-availability-checker.directive'; import { FlowCoreProviderService, FlowResizeBatchProcessorService, RendererService } from '../../services'; +import { TemplateProviderService } from '../../services/template-provider/template-provider.service'; import { NgDiagramConfig, NgDiagramEdgeTemplateMap, NgDiagramNodeTemplateMap } from '../../types'; import { BUILTIN_MIDDLEWARES } from '../../utils/create-middlewares'; import { NgDiagramCanvasComponent } from '../canvas/ng-diagram-canvas.component'; @@ -79,6 +80,7 @@ export class NgDiagramComponent implements OnInit, OnDestroy { private readonly flowCoreProvider = inject(FlowCoreProviderService); private readonly renderer = inject(RendererService); private readonly flowResizeBatchProcessor = inject(FlowResizeBatchProcessorService); + private readonly templateProviderService = inject(TemplateProviderService); private initializedModel: ModelAdapter | null = null; private resizeObserver: ResizeObserver | null = null; @@ -155,6 +157,16 @@ export class NgDiagramComponent implements OnInit, OnDestroy { this.setupEventBridge(); } }); + + effect(() => { + const nodeTemplateMap = this.nodeTemplateMap(); + this.templateProviderService.setNodeTemplateMap(nodeTemplateMap); + }); + + effect(() => { + const edgeTemplateMap = this.edgeTemplateMap(); + this.templateProviderService.setEdgeTemplateMap(edgeTemplateMap); + }); } /** @ignore */ @@ -199,14 +211,11 @@ export class NgDiagramComponent implements OnInit, OnDestroy { * @throws This method does not throw exceptions - it handles all edge cases gracefully */ getNodeTemplate(nodeType: Node['type']) { - return this.nodeTemplateMap().get(nodeType || '') ?? null; + return this.templateProviderService.getNodeTemplate(nodeType); } getEdgeTemplate(edgeType: Edge['type']) { - if (!edgeType) { - return null; - } - return this.edgeTemplateMap().get(edgeType) ?? null; + return this.templateProviderService.getEdgeTemplate(edgeType); } isGroup(node: Node) { diff --git a/packages/ng-diagram/projects/ng-diagram/src/lib/providers/ng-diagram.providers.ts b/packages/ng-diagram/projects/ng-diagram/src/lib/providers/ng-diagram.providers.ts index 5d0d4cd90..c1ddd0428 100644 --- a/packages/ng-diagram/projects/ng-diagram/src/lib/providers/ng-diagram.providers.ts +++ b/packages/ng-diagram/projects/ng-diagram/src/lib/providers/ng-diagram.providers.ts @@ -15,6 +15,7 @@ import { LinkingEventService } from '../services/input-events/linking-event.serv import { ManualLinkingService } from '../services/input-events/manual-linking.service'; import { PaletteService } from '../services/palette/palette.service'; import { RendererService } from '../services/renderer/renderer.service'; +import { TemplateProviderService } from '../services/template-provider/template-provider.service'; import { UpdatePortsService } from '../services/update-ports/update-ports.service'; /** @@ -61,5 +62,6 @@ export function provideNgDiagram(): Provider[] { NgDiagramGroupsService, LinkingEventService, ManualLinkingService, + TemplateProviderService, ]; } diff --git a/packages/ng-diagram/projects/ng-diagram/src/lib/services/template-provider/template-provider.service.ts b/packages/ng-diagram/projects/ng-diagram/src/lib/services/template-provider/template-provider.service.ts new file mode 100644 index 000000000..75a38edc7 --- /dev/null +++ b/packages/ng-diagram/projects/ng-diagram/src/lib/services/template-provider/template-provider.service.ts @@ -0,0 +1,54 @@ +import { inject, Injectable } from '@angular/core'; +import { Edge, Node } from '../../../public-api'; +import { NgDiagramEdgeTemplateMap, NgDiagramNodeTemplateMap } from '../../types'; +import { FlowCoreProviderService } from '../flow-core-provider/flow-core-provider.service'; + +@Injectable() +export class TemplateProviderService { + private flowConfig = inject(FlowCoreProviderService); + private nodeTemplateMap = new NgDiagramNodeTemplateMap(); + private edgeTemplateMap = new NgDiagramEdgeTemplateMap(); + + private accessedNodeTypes = new Set(); + private accessedEdgeTypes = new Set(); + + setNodeTemplateMap(map: NgDiagramNodeTemplateMap): void { + this.accessedNodeTypes.clear(); + this.nodeTemplateMap = map; + } + + setEdgeTemplateMap(map: NgDiagramEdgeTemplateMap): void { + this.accessedEdgeTypes.clear(); + this.edgeTemplateMap = map; + } + + getNodeTemplate(nodeType: Node['type']) { + if (nodeType === undefined) { + return null; + } + + const template = this.nodeTemplateMap.get(nodeType || ''); + + if (!template && !this.accessedNodeTypes.has(nodeType) && this.flowConfig.provide().config.debugMode) { + console.warn(`No template found for node type: '${nodeType}'`); + this.accessedNodeTypes.add(nodeType); + } + + return template ?? null; + } + + getEdgeTemplate(edgeType: Edge['type']) { + if (edgeType === undefined) { + return null; + } + + const template = this.edgeTemplateMap.get(edgeType || ''); + + if (!template && !this.accessedEdgeTypes.has(edgeType) && this.flowConfig.provide().config.debugMode) { + console.warn(`No template found for edge type: '${edgeType}'`); + this.accessedEdgeTypes.add(edgeType); + } + + return template ?? null; + } +}