mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
docs: Adds documentation for the NG0919 error
Adds a new documentation page for the NG0919 error, which indicates a circular dependency in Angular applications. fixes #65968
This commit is contained in:
parent
5f01f121df
commit
bb65520991
4 changed files with 102 additions and 2 deletions
99
adev/src/content/reference/errors/NG0919.md
Normal file
99
adev/src/content/reference/errors/NG0919.md
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
# Circular Dependency Detected
|
||||
|
||||
Angular detected a circular dependency between components, directives, or pipes. This error occurs when component A imports component B, and component B (directly or indirectly) imports component A, creating a cycle.
|
||||
|
||||
This circular reference prevents Angular from properly initializing the components, resulting in an error like:
|
||||
|
||||
```text
|
||||
NG0919: Cannot read @Component metadata. This can indicate a runtime circular dependency in your app that needs to be resolved.
|
||||
```
|
||||
|
||||
In older Angular versions, you might instead see an error like:
|
||||
|
||||
```text
|
||||
Cannot read properties of undefined (reading 'ɵcmp')
|
||||
```
|
||||
|
||||
## Common Causes
|
||||
|
||||
### Mutual Component Imports
|
||||
|
||||
The most common cause is when two components import each other:
|
||||
|
||||
```angular-ts {header:"parent.component.ts"}
|
||||
import {Component} from '@angular/core';
|
||||
import {ChildComponent} from './child.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-parent',
|
||||
imports: [ChildComponent],
|
||||
template: '<app-child/>',
|
||||
})
|
||||
export class ParentComponent {}
|
||||
```
|
||||
|
||||
```angular-ts {header:"child.component.ts"}
|
||||
import {Component} from '@angular/core';
|
||||
import {ParentComponent} from './parent.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-child',
|
||||
imports: [ParentComponent],
|
||||
template: '<app-parent/>',
|
||||
})
|
||||
export class ChildComponent {}
|
||||
```
|
||||
|
||||
### Indirect Circular References
|
||||
|
||||
Circular dependencies can also occur through intermediate files:
|
||||
|
||||
```text
|
||||
ComponentA -> ComponentB -> ComponentC -> ComponentA
|
||||
```
|
||||
|
||||
## Resolving the error
|
||||
|
||||
### Refactor shared logic
|
||||
|
||||
Move shared functionality to a separate file that doesn't import either component:
|
||||
|
||||
```angular-ts {header:"shared.service.ts"}
|
||||
import {Injectable} from '@angular/core';
|
||||
|
||||
@Injectable({providedIn: 'root'})
|
||||
export class SharedService {
|
||||
// Shared logic here
|
||||
}
|
||||
```
|
||||
|
||||
### Use type-only imports
|
||||
|
||||
If you only need types for TypeScript, use `import type`:
|
||||
|
||||
```ts
|
||||
import type {ParentComponent} from './parent.component';
|
||||
```
|
||||
|
||||
Type-only imports are erased at compile time and don't contribute to runtime circular dependencies.
|
||||
|
||||
### Restructure component hierarchy
|
||||
|
||||
Consider whether the circular dependency indicates a design issue. Often, extracting shared functionality into a third component or service is the cleanest solution.
|
||||
|
||||
### Debugging complex circular dependencies
|
||||
|
||||
For complex applications with many modules, circular dependencies can be difficult to identify manually. Consider using tools like [madge](https://www.npmjs.com/package/madge) to visualize and detect circular imports:
|
||||
|
||||
```bash
|
||||
# Install madge
|
||||
npm install -g madge
|
||||
|
||||
# Check for circular dependencies
|
||||
madge --circular --extensions ts ./src
|
||||
|
||||
# Generate a visual graph
|
||||
madge --circular --extensions ts --image graph.svg ./src
|
||||
```
|
||||
|
||||
These tools can help identify circular dependency chains across your entire project and generate visual dependency graphs.
|
||||
|
|
@ -25,6 +25,7 @@
|
|||
| `NG0750` | [@defer dependencies failed to load](errors/NG0750) |
|
||||
| `NG0910` | [Unsafe bindings on an iframe element](errors/NG0910) |
|
||||
| `NG0912` | [Component ID generation collision](errors/NG0912) |
|
||||
| `NG0919` | [Circular Dependency Detected](errors/NG0919) |
|
||||
| `NG0955` | [Track expression resulted in duplicated keys for a given collection](errors/NG0955) |
|
||||
| `NG0956` | [Tracking expression caused re-creation of the DOM structure](errors/NG0956) |
|
||||
| `NG01101` | [Wrong Async Validator Return Type](errors/NG01101) |
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ export const enum RuntimeErrorCode {
|
|||
// (undocumented)
|
||||
CYCLIC_DI_DEPENDENCY = -200,
|
||||
// (undocumented)
|
||||
DEF_TYPE_UNDEFINED = 919,
|
||||
DEF_TYPE_UNDEFINED = -919,
|
||||
// (undocumented)
|
||||
DEFER_IN_HMR_MODE = -751,
|
||||
// (undocumented)
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ export const enum RuntimeErrorCode {
|
|||
MISSING_DIRECTIVE_DEFINITION = 916,
|
||||
NO_COMPONENT_FACTORY_FOUND = 917,
|
||||
EXTERNAL_RESOURCE_LOADING_FAILED = 918,
|
||||
DEF_TYPE_UNDEFINED = 919,
|
||||
DEF_TYPE_UNDEFINED = -919,
|
||||
|
||||
// Signal integration errors
|
||||
REQUIRED_INPUT_NO_VALUE = -950,
|
||||
|
|
|
|||
Loading…
Reference in a new issue