synergycodes/ng-diagram/ng-diagram-model-init
Claude Code and agent skill by synergycodes/ng-diagram
- community
Checking that the SKILL.md file is still in the repository.
Use when creating, loading or swapping an ng-diagram model (initializeModel), waiting for diagramInit/isInitialized, edits lost after a model swap or @if/tab switch, or "Library engine not initialized yet", NG0203, "Measurement timeout reached".
Install
npx vskill@latest install synergycodes/ng-diagram/ng-diagram-model-initSKILL.md
ng-diagram model initialization
Create models with initializeModel, load and switch them, know when service calls work, wait for initialization, and fix init-time warnings. Save/load format and custom adapters: ng-diagram-persistence. Model fields: ng-diagram-fundamentals (references/model-reference.md).
Rules
- Create every model with `initializeModel(data?, injector?, options?)`, or
initializeModelAdapter(adapter, data?, injector?, options?)for your ownModelAdapter(since 1.1.0). They strip stale runtime fields and add internal ids; an adapter that skips this step can block measurement at init. - Pass an `Injector` outside an injection context: after an
await, in event handlers and timers, and insidecomputed,effectandlinkedSignal. Field initializers and constructors need none. Without it Angular throws NG0203 (effect() can only be used within an injection context ...). - A new model object means a full re-initialization: the engine is destroyed and created again (from the current
[config]), every element is measured again,isInitialized()goesfalseand back totrue, and(diagramInit)fires again. Binding the same object again does nothing. - Service methods throw `[ngDiagram] Library engine not initialized yet.` until `<ng-diagram>` has created its engine, for example in the constructor or
ngOnInitof the component that renders it, or of a toolbar or sidebar declared next to<ng-diagram>in the same template. Start your logic from(diagramInit)or anisInitialized()effect. - Calls right after you assign a new model reach the old one. The swap happens on the next change detection, and the old model is then thrown away with your changes. Put the data into
initializeModel(...), or make the calls in(diagramInit). - A model belongs to one diagram instance. When
<ng-diagram>is destroyed or gets another model, the old adapter is destroyed: the default adapter clears its nodes and edges and stops notifying. Create a new model each time the diagram is created again (an@if, a tab, a route), from content you saved before the switch (recipe below).
Lifecycle
<ng-diagram>renders and creates the engine from[model],[config]and[middlewares]. Service methods work from here, but nothing is measured yet.- Nodes, ports and labels render on a hidden canvas; a
ResizeObservermeasures them. - When every visible element is measured, the init pass runs (edge routing, z-index) and the engine emits
diagramInit. - Then
isInitialized()becomestrue, the(diagramInit)output fires,zoom.zoomToFit.onInitruns if enabled, and the canvas becomes visible.
The nodes(), edges() and metadata() signals of NgDiagramModelService start updating only after step 4.
Static model, react to init
To fit on every load without code, set zoom: { zoomToFit: { onInit: true } } in [config] (not with virtualization, see Edge cases).
Load from an API or switch diagrams
- A signal keeps the swap visible to
OnPushand zoneless components. - Work that must follow each load (layout, selection, focus) belongs in
(diagramInit), which fires after every initialization.
Keep the content when the diagram leaves and comes back
When an @if, a tab or a route removes <ng-diagram>, its model is destroyed and emptied. Save the content while <ng-diagram> still exists, for example in the handler that switches the tab, and create the next model from it. ngOnDestroy of the component that renders <ng-diagram> is too late: Angular destroys <ng-diagram> first, so service calls throw and the default model is already empty. Content that must survive any teardown (a route change) belongs in your own store (ng-diagram-persistence).
Reactive model from a signal (since 1.2.0)
Every new diagramData value is a full re-initialization; setting the same object again is skipped. Do not feed sources that change often: apply small changes with NgDiagramModelService instead (ng-diagram-state-updates). Before 1.2.0, initializeModel inside computed threw NG0602.
Wait for init in another component
The three ways to wait:
(diagramInit)on<ng-diagram>: fires after every initialization and survives model swaps.isInitialized()fromNgDiagramService: a signal for templates and effects, in any component under the sameprovideNgDiagram().addEventListenerOnce('diagramInit', callback): registers on the current engine only. It throws before the engine exists, and a listener added just before a model swap dies with the old engine. Inside it,isInitialized()is stillfalse. Prefer the two above.
Keep runtime fields from saved data (since 1.3.0)
initializeModel() removes runtime fields from every element: on nodes selected, measuredPorts, measuredBounds, computedZIndex, computedHidden; on edges measuredLabels, computedZIndex, computedHidden and sourcePosition/targetPosition of connected ends. InitializeModelOptions replaces these strip functions, at your own risk: wrap the default and add back only what you need.
Keeping measured fields (measuredPorts, measuredLabels, ...) makes the library skip fresh measurement and breaks the diagram. For the default model the same functions also run in toJSON().
Measurement timeout at init
Initialization waits until every visible node, port and label has a real size (width and height above 0). Elements that never get one keep the canvas hidden until 2-second safety timeouts expire, and the console shows:
[InitUpdater] Measurement timeout reached. Some entities may not be measurable (e.g., display: none). ...with{ nodes: { expected, measured }, ports: ..., labels: ... }. Init is then forced to finish.[DiagramInitEmitter] Measurement timeout reached from last measurement. Emitting diagramInit event anyway. ..., thenTotal unmeasured elements: Nand lists such asUnmeasured nodes (2): ['a', 'b']orUnmeasured node ports (1): ['a:port-left']. This one fires 2 s after the last measurement progress, so a broken load can take about 4 s.
Causes and fixes:
| Cause | Fix | |
|---|---|---|
Nodes, ports or labels hidden with CSS display: none | Use the hidden flag on nodes and edges or the hidden input on ports and labels (since 1.4.0); hidden elements create no measurement expectations. See ng-diagram-visibility. | |
<ng-diagram> inside a hidden container (inactive tab, collapsed panel, display: none parent) | Create the diagram component, with a new model, only when the container is visible (@if). | |
A custom ModelAdapter bound without initializeModelAdapter() | Pass it through initializeModelAdapter(adapter, data?, injector?) first. | |
| A node, port or label element in your template renders with zero width or height | Give it a size (ng-diagram-custom-nodes, ng-diagram-ports, ng-diagram-custom-edges). |
A rare [ngDiagram] Initialization stabilization failed. (console error) also forces init to finish; the message lists the same causes.
Edge cases
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 90 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/ng-diagram-model-init/SKILL.md
Popularity
- 7-day trend score
- 0
Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/synergycodes/ng-diagram/ng-diagram-model-init)