> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/angular/angular/llms.txt
> Use this file to discover all available pages before exploring further.

# NgModules

> Understanding NgModule for organizing Angular applications (legacy but still widely used)

NgModules are TypeScript classes decorated with `@NgModule` that organize Angular applications into cohesive blocks of functionality. While standalone components are now the recommended approach, NgModules are still widely used in existing applications.

<Warning>
  Standalone components are the recommended approach for new Angular applications. NgModules are considered legacy but remain fully supported.
</Warning>

## What is an NgModule?

An NgModule is a container for components, directives, pipes, and services that work together as a functional unit:

```typescript theme={null}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { UserListComponent } from './user-list.component';
import { UserService } from './user.service';

@NgModule({
  declarations: [    // Components, directives, and pipes
    AppComponent,
    UserListComponent
  ],
  imports: [         // Other modules
    BrowserModule
  ],
  providers: [       // Services
    UserService
  ],
  bootstrap: [       // Root component(s)
    AppComponent
  ]
})
export class AppModule { }
```

## NgModule Metadata

The `@NgModule` decorator accepts metadata:

### declarations

Components, directives, and pipes that belong to this module:

```typescript theme={null}
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { UserListComponent } from './user-list.component';
import { UserDetailComponent } from './user-detail.component';
import { HighlightDirective } from './highlight.directive';
import { TruncatePipe } from './truncate.pipe';

@NgModule({
  declarations: [
    UserListComponent,
    UserDetailComponent,
    HighlightDirective,
    TruncatePipe
  ],
  imports: [CommonModule],
  exports: [UserListComponent, UserDetailComponent]
})
export class UserModule { }
```

<Note>
  Each component, directive, or pipe can only be declared in ONE NgModule. Declaring in multiple modules will cause a compilation error.
</Note>

### imports

Other modules whose exported classes are needed:

```typescript theme={null}
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { RouterModule } from '@angular/router';

@NgModule({
  imports: [
    CommonModule,           // ngIf, ngFor, etc.
    FormsModule,            // ngModel
    ReactiveFormsModule,    // Reactive forms
    HttpClientModule,       // HTTP client
    RouterModule.forChild(routes)
  ]
})
export class FeatureModule { }
```

### exports

Make components, directives, and pipes available to other modules:

```typescript theme={null}
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ButtonComponent } from './button.component';
import { CardComponent } from './card.component';
import { HighlightDirective } from './highlight.directive';

@NgModule({
  declarations: [
    ButtonComponent,
    CardComponent,
    HighlightDirective,
    InternalComponent  // Not exported - only for internal use
  ],
  imports: [CommonModule],
  exports: [
    // Export own declarations
    ButtonComponent,
    CardComponent,
    HighlightDirective,
    // Re-export other modules
    CommonModule
  ]
})
export class SharedModule { }
```

### providers

Services available to the module's injector:

```typescript theme={null}
import { NgModule } from '@angular/core';
import { UserService } from './user.service';
import { AuthService } from './auth.service';
import { LoggerService } from './logger.service';
import { API_URL } from './tokens';

@NgModule({
  providers: [
    UserService,
    AuthService,
    LoggerService,
    { provide: API_URL, useValue: 'https://api.example.com' }
  ]
})
export class CoreModule { }
```

### bootstrap

The root component(s) to bootstrap:

```typescript theme={null}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule],
  bootstrap: [AppComponent]  // Only in root module
})
export class AppModule { }
```

## Common Module Patterns

### Root Module (AppModule)

The main application module:

```typescript theme={null}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { CoreModule } from './core/core.module';
import { SharedModule } from './shared/shared.module';

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    HttpClientModule,
    CoreModule,
    SharedModule,
    AppRoutingModule  // Should be last
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }
```

### Core Module

Singleton services and app-wide components:

```typescript theme={null}
import { NgModule, Optional, SkipSelf } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AuthService } from './auth.service';
import { LoggerService } from './logger.service';
import { HeaderComponent } from './header.component';
import { FooterComponent } from './footer.component';

@NgModule({
  declarations: [HeaderComponent, FooterComponent],
  imports: [CommonModule],
  exports: [HeaderComponent, FooterComponent],
  providers: [AuthService, LoggerService]
})
export class CoreModule {
  constructor(@Optional() @SkipSelf() parentModule?: CoreModule) {
    if (parentModule) {
      throw new Error('CoreModule is already loaded. Import it only in AppModule');
    }
  }
}
```

### Shared Module

Reusable components, directives, and pipes:

```typescript theme={null}
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { ButtonComponent } from './button.component';
import { CardComponent } from './card.component';
import { LoaderComponent } from './loader.component';
import { TruncatePipe } from './truncate.pipe';
import { HighlightDirective } from './highlight.directive';

@NgModule({
  declarations: [
    ButtonComponent,
    CardComponent,
    LoaderComponent,
    TruncatePipe,
    HighlightDirective
  ],
  imports: [CommonModule, FormsModule],
  exports: [
    // Export own declarations
    ButtonComponent,
    CardComponent,
    LoaderComponent,
    TruncatePipe,
    HighlightDirective,
    // Re-export common modules
    CommonModule,
    FormsModule
  ]
})
export class SharedModule { }
```

### Feature Module

Domain-specific functionality:

```typescript theme={null}
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule, Routes } from '@angular/router';
import { SharedModule } from '../shared/shared.module';
import { UserListComponent } from './user-list.component';
import { UserDetailComponent } from './user-detail.component';
import { UserService } from './user.service';

const routes: Routes = [
  { path: '', component: UserListComponent },
  { path: ':id', component: UserDetailComponent }
];

@NgModule({
  declarations: [
    UserListComponent,
    UserDetailComponent
  ],
  imports: [
    CommonModule,
    SharedModule,
    RouterModule.forChild(routes)
  ],
  providers: [UserService]
})
export class UserModule { }
```

## Lazy Loading Modules

Load modules on demand:

```typescript theme={null}
// app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

const routes: Routes = [
  {
    path: 'users',
    loadChildren: () => import('./user/user.module').then(m => m.UserModule)
  },
  {
    path: 'products',
    loadChildren: () => import('./product/product.module').then(m => m.ProductModule)
  }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }
```

## ModuleWithProviders

Configure module with runtime values:

```typescript theme={null}
import { NgModule, ModuleWithProviders } from '@angular/core';
import { CommonModule } from '@angular/common';
import { CONFIG_TOKEN, ModuleConfig } from './config';
import { ConfigurableService } from './configurable.service';

@NgModule({
  imports: [CommonModule]
})
export class ConfigurableModule {
  static forRoot(config: ModuleConfig): ModuleWithProviders<ConfigurableModule> {
    return {
      ngModule: ConfigurableModule,
      providers: [
        ConfigurableService,
        { provide: CONFIG_TOKEN, useValue: config }
      ]
    };
  }

  static forChild(): ModuleWithProviders<ConfigurableModule> {
    return {
      ngModule: ConfigurableModule,
      providers: []
    };
  }
}

// Usage in AppModule
@NgModule({
  imports: [
    ConfigurableModule.forRoot({ apiUrl: 'https://api.example.com' })
  ]
})
export class AppModule { }

// Usage in feature module
@NgModule({
  imports: [
    ConfigurableModule.forChild()
  ]
})
export class FeatureModule { }
```

## Migration to Standalone

Migrate from NgModules to standalone components:

```typescript theme={null}
// Before (NgModule)
@NgModule({
  declarations: [UserComponent],
  imports: [CommonModule, FormsModule],
  exports: [UserComponent]
})
export class UserModule { }

// After (Standalone)
@Component({
  selector: 'app-user',
  standalone: true,
  imports: [CommonModule, FormsModule],
  template: `...`
})
export class UserComponent { }
```

Use Angular CLI to help with migration:

```bash theme={null}
ng generate @angular/core:standalone
```

## Common Mistakes

<Warning>
  Avoid these common NgModule mistakes:

  1. **Declaring in multiple modules** - Each component can only be in ONE NgModule
  2. **Not importing CommonModule** - Feature modules need CommonModule, not BrowserModule
  3. **Importing modules in wrong order** - RouterModule should typically be last
  4. **Providing services in feature modules** - Use `providedIn: 'root'` instead
  5. **Re-importing HttpClientModule** - Import only once in AppModule or CoreModule
</Warning>

## Best Practices

1. **Consider standalone first** - For new applications
2. **One core module** - Import once in AppModule
3. **Shared module for common items** - Import in feature modules
4. **Feature modules for domains** - Organize by business domain
5. **Lazy load feature modules** - Improve initial load time
6. **Use forRoot/forChild pattern** - For configurable modules

## Next Steps

<CardGroup cols={2}>
  <Card title="Components" href="/concepts/components">
    Learn about standalone components
  </Card>

  <Card title="Dependency Injection" href="/concepts/dependency-injection">
    Understand Angular's DI system
  </Card>
</CardGroup>
