Introduction

Angular standalone components (introduced in Angular 14) can be used without NgModules, but when mixing standalone and module-based components, the standalone component must be properly imported into the module that declares or uses it. When this is misconfigured, the component is not recognized:

bash
Error: 'app-user-profile' is not a known element:
1. If 'app-user-profile' is an Angular component, then verify that it is part of this module.
2. If 'app-user-profile' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to this module.

Symptoms

  • Template error: "is not a known element" for a standalone component
  • Standalone component renders in its own route but not when used as a child component
  • Component works when used directly in a standalone bootstrap but not in an NgModule
  • Error occurs after converting a component to standalone
  • Component imports work in one module but not another

Common Causes

  • Standalone component not added to the imports array of the consuming NgModule
  • Component has standalone: false but is being treated as standalone
  • Importing the component file but the export name does not match
  • Circular imports between standalone component and NgModule
  • Standalone component's own imports (CommonModule, etc.) are missing

Step-by-Step Fix

  1. 1.Import the standalone component in the NgModule:
  2. 2.```typescript
  3. 3.// user-profile.component.ts (standalone)
  4. 4.@Component({
  5. 5.selector: 'app-user-profile',
  6. 6.standalone: true,
  7. 7.imports: [CommonModule],
  8. 8.template: <div class="profile">{{ user.name }}</div>,
  9. 9.})
  10. 10.export class UserProfileComponent {
  11. 11.@Input() user: any;
  12. 12.}

// dashboard.module.ts (NgModule that uses the standalone component) @NgModule({ declarations: [DashboardComponent], imports: [ CommonModule, UserProfileComponent, // Add standalone component here ], }) export class DashboardModule {} ```

  1. 1.Verify the component is correctly configured as standalone:
  2. 2.```typescript
  3. 3.@Component({
  4. 4.selector: 'app-widget',
  5. 5.standalone: true, // Must be true
  6. 6.imports: [CommonModule, MatButtonModule],
  7. 7.template: <mat-button>Click</mat-button>,
  8. 8.})
  9. 9.export class WidgetComponent {}
  10. 10.`
  11. 11.Handle standalone components in lazy loaded routes:
  12. 12.```typescript
  13. 13.// app.routes.ts
  14. 14.const routes: Routes = [
  15. 15.{
  16. 16.path: 'settings',
  17. 17.loadComponent: () => import('./settings/settings.component')
  18. 18..then(m => m.SettingsComponent), // Standalone component
  19. 19.},
  20. 20.];
  21. 21.`
  22. 22.For standalone components importing other standalone components:
  23. 23.```typescript
  24. 24.@Component({
  25. 25.selector: 'app-dashboard',
  26. 26.standalone: true,
  27. 27.imports: [
  28. 28.CommonModule,
  29. 29.UserProfileComponent, // Another standalone component
  30. 30.WidgetComponent, // Another standalone component
  31. 31.],
  32. 32.template: `
  33. 33.<app-user-profile [user]="currentUser"></app-user-profile>
  34. 34.<app-widget></app-widget>
  35. 35.`,
  36. 36.})
  37. 37.export class DashboardComponent {}
  38. 38.`

Prevention

  • Always include standalone: true in the component decorator for standalone components
  • Add standalone components to the imports array of the consuming NgModule, not declarations
  • Use loadComponent for lazy loading standalone components instead of loadChildren
  • Keep a consistent naming convention: standalone components should be clearly identifiable
  • Document which components are standalone vs module-based in your component registry
  • Use Angular's schematic to generate standalone components: ng generate component --standalone
  • Test standalone components both in isolation and when imported into NgModules
  • Run ng build after converting components to standalone to verify all imports are correct