Model Initialization
Model initialization and reinitialization are crucial concepts in ngDiagram that determine when and how your diagram data is set up and when it’s safe to perform operations on the model. Understanding these mechanisms is essential for building robust applications that handle dynamic data loading and model switching.
There are various scenarios when and how to initialize a model, depending on your application’s requirements and data flow. For comprehensive information about state management patterns and model operations, see State Management.
Model Initialization
Section titled “Model Initialization”The initializeModel function is the primary way to create a model for use in ngDiagram.
It creates a model instance that wraps your diagram data and provides reactive state management.
Basic Model Creation
Section titled “Basic Model Creation”import { initializeModel } from 'ng-diagram';
// Create a model with default values (empty nodes, edges, and default metadata)const model = initializeModel();
// Create a model with initial dataconst model = initializeModel({ nodes: [ { id: '1', position: { x: 100, y: 150 }, data: { label: 'Node 1' }, }, { id: '2', position: { x: 400, y: 150 }, data: { label: 'Node 2' }, }, ], edges: [ { id: 'edge-1', source: '1', target: '2', sourcePort: 'port-right', targetPort: 'port-left', data: {}, }, ], metadata: { viewport: { x: 0, y: 0, scale: 1 }, },});Model Reinitialization
Section titled “Model Reinitialization”Sometimes you need to replace the entire model with new data. This commonly happens when:
- Loading data asynchronously - Fetching diagram data from an API
- Switching between different diagrams - User selects a different model from a list
- Resetting the diagram - Clearing all data and starting fresh
Reinitializing with New Data
Section titled “Reinitializing with New Data”export class MyComponent { private readonly injector = inject(Injector);
model = initializeModel();
async loadDiagramFromAPI(diagramId: string) { // Fetch data asynchronously const diagramData = await this.dataService.getDiagramData(diagramId);
// Reinitialize model with new data this.model = initializeModel(diagramData, this.injector); }
switchToDiagram(diagramData: Partial<Model>) { // Switch to a different diagram this.model = initializeModel(diagramData, this.injector); }
resetDiagram() { // Reset to empty diagram this.model = initializeModel({}, this.injector); }}Timing and Events
Section titled “Timing and Events”When a model is reinitialized, the diagram goes through a complete initialization process. All nodes and edges need to be measured and positioned before the diagram is fully ready. You need to wait for this process to complete before performing operations on the model.
Initialization Process
Section titled “Initialization Process”The initialization process involves several steps:
- Model Assignment – A new model is assigned to the diagram component.
- Logic Recreation – The internal core logic is destroyed and recreated. Because the logic is recreated, the
isInitializedsignal has its default value (false). - Element Measurement – All nodes, edges, and their internal parts are measured.
- Layout Calculation – Positions and sizes are calculated.
- Event Emission & Signal Update – The
diagramInitevent is emitted when everything is ready, and theisInitializedsignal is set totrue.
Waiting for Initialization
Section titled “Waiting for Initialization”There are three main ways to detect when the diagram is fully initialized:
Using the diagramInit Event
Section titled “Using the diagramInit Event”The most convenient way is to listen for the diagramInit event from the ng-diagram component:
export class MyComponent { model = initializeModel(); private injector = inject(Injector);
onDiagramInit(event: DiagramInitEvent): void { console.log('Diagram is fully initialized'); console.log('Nodes:', event.nodes); console.log('Edges:', event.edges); console.log('Viewport:', event.viewport);
// Now it's safe to perform operations this.performPostInitializationLogic(); }
private performPostInitializationLogic() { // Your logic here - diagram is fully ready this.modelService.addNodes([...]); this.modelService.updateNodeData('node-1', { ... }); }}<ng-diagram [model]="model" (diagramInit)="onDiagramInit($event)"> </ng-diagram>Using the isInitialized Signal
Section titled “Using the isInitialized Signal”You can also check the isInitialized signal from NgDiagramService:
export class MyComponent { private ngDiagramService = inject(NgDiagramService); private modelService = inject(NgDiagramModelService);
constructor() { effect(() => { if (this.ngDiagramService.isInitialized()) { this.performPostInitializationLogic(); } }); }}Using Event Listener Registration
Section titled “Using Event Listener Registration”For more advanced scenarios, you can register event listeners programmatically:
export class MyComponent { private ngDiagramService = inject(NgDiagramService); private modelService = inject(NgDiagramModelService);
ngOnInit() { // Register a one-time listener for diagram initialization. // Alternatively, you can use addEventListener, but make sure to // unregister it when no longer needed to avoid memory leaks. this.ngDiagramService.addEventListenerOnce('diagramInit', (event) => { console.log('Diagram initialized via event listener'); this.performPostInitializationLogic(event); }); }
private performPostInitializationLogic(event: DiagramInitEvent) { // Your logic here — at this stage you can safely read the measured // nodes, edges and their internal parts (positions, sizes, points, etc.). }}Best Practices
Section titled “Best Practices”Always Wait for Initialization
Section titled “Always Wait for Initialization”// ❌ Don't do this - operations may fail or be ignoredthis.model = initializeModel(newData, this.injector);this.modelService.addNodes([...]); // This might not work!
// ✅ Do this insteadthis.model = initializeModel(newData, this.injector);// Wait for onDiagramInit() to be called, then perform operationsUse Transactions
Section titled “Use Transactions”When performing multiple operations after initialization, wrap them in a transaction:
onDiagramInit(event: DiagramInitEvent): void { this.ngDiagramService.transaction(() => { this.modelService.addNodes([...]); this.modelService.addEdges([...]); this.modelService.updateMetadata({ ... }); });}Memory Management
Section titled “Memory Management”When switching between models frequently, be aware of memory usage:
export class MemoryConsciousComponent { model = initializeModel(); private injector = inject(Injector); private currentDiagramId: string | null = null;
async switchToDiagram(diagramId: string) { // Avoid unnecessary reinitializations if (this.currentDiagramId === diagramId) { return; }
this.currentDiagramId = diagramId; const diagramData = await this.diagramAPI.getDiagram(diagramId); this.model = initializeModel(diagramData, this.injector); }}Troubleshooting
Section titled “Troubleshooting”Common Issues
Section titled “Common Issues”Operations not working after model reinitialization:
- Ensure you’re waiting for the
diagramInitevent - Check that you’re using the model service, not the model directly
Initialization events not firing:
- Verify that the diagram component is properly rendered
- Check that the model is actually changing (not the same reference)
Understanding model initialization and reinitialization is key to building robust ngDiagram applications that can handle dynamic data loading and model switching while maintaining proper timing and state management.