Kurs Angular · Moduł 3: Moduły

NgModules - System Klanowy

2 min czytania ·
W tej lekcji4

W feudalnej Japonii każdy klan (han) miał swoją strukturę, terytorium i zasoby. W Angularze moduły pełnią podobną rolę - grupują powiązane elementy i definiują ich zakres.

Czym są NgModules?

NgModules to kontenery organizacyjne w Angular. Choć od Angular 17+ preferowane są Standalone Components, znajomość modułów jest kluczowa dla:

  • Pracy z legacy projektami
  • Rozumienia architektury Angular
  • Lazy loading (nadal popularny z modułami)

Anatomia NgModule

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';

// Komponenty tego modułu
import { SamuraiListComponent } from './samurai-list.component';
import { SamuraiCardComponent } from './samurai-card.component';
import { SamuraiDetailComponent } from './samurai-detail.component';

// Serwisy
import { SamuraiService } from './samurai.service';

@NgModule({
  // Komponenty, dyrektywy, pipes NALEŻĄCE do tego modułu
  declarations: [
    SamuraiListComponent,
    SamuraiCardComponent,
    SamuraiDetailComponent
  ],

  // Inne moduły, których POTRZEBUJEMY
  imports: [
    CommonModule,  // *ngIf, *ngFor, async pipe, etc.
    FormsModule    // ngModel, formularze template-driven
  ],

  // Elementy UDOSTĘPNIANE innym modułom
  exports: [
    SamuraiListComponent,
    SamuraiCardComponent
  ],

  // Serwisy dostępne w tym module (legacy sposób)
  providers: [
    SamuraiService
  ]
})
export class SamuraiModule { }

Uwaga dla Angulara 19 i nowszego: komponenty są domyślnie samodzielne (standalone), a takiego komponentu nie wolno wpisać do declarations - kompilator zgłosi błąd NG6008. Komponent, który ma należeć do NgModule, musi mieć w dekoratorze standalone: false; komponent samodzielny dołączasz do modułu przez imports.

Właściwości Dekoratora @NgModule

WłaściwośćOpisPrzykład
declarationsKomponenty, dyrektywy, pipes należące do modułu[MyComponent, MyDirective]
importsModuły, których potrzebujemy[CommonModule, FormsModule]
exportsElementy udostępniane na zewnątrz[MyComponent]
providersSerwisy (legacy, lepiej używać providedIn)[MyService]
bootstrapGłówny komponent (tylko AppModule)[AppComponent]

AppModule - Centralny Zamek

// app.module.ts - główny moduł aplikacji
@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,      // Wymagany dla aplikacji przeglądarkowych
    AppRoutingModule,   // Routing
    SamuraiModule,      // Nasz feature module
    DojoModule
  ],
  providers: [],
  bootstrap: [AppComponent]  // Komponent startowy
})
export class AppModule { }

Myśl o module jak o klanie - declarations to wojownicy, którzy do niego należą, imports to sojusze z innymi klanami, exports to siły użyczane na zewnątrz - a AppModule z polem bootstrap jest zamkiem, od którego rusza cała aplikacja.

Kod do tej lekcji: src/app/app.component.ts
import { Component } from '@angular/core';
import { SamuraiModule } from './samurai/samurai.module';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [SamuraiModule],
  template: `
    <div class="dojo">
      <header>
        <h1>Klany i Prowincje</h1>
        <p>Moduł 3: Organizacja Kodu w Angular</p>
      </header>

      <main>
        <section class="info-panel">
          <h2>Struktura Modułów</h2>
          <p>Klany (moduły) organizują wojowników (komponenty) w logiczne grupy.</p>
          <ul>
            <li>Feature Modules - funkcjonalności</li>
            <li>Shared Modules - współdzielone elementy</li>
            <li>Core Module - singleton services</li>
          </ul>
        </section>

        <section class="demo-panel">
          <h2>Klan Samurajów (Feature Module)</h2>
          <app-samurai-list></app-samurai-list>
        </section>
      </main>
    </div>
  `,
  styles: [`
    .dojo {
      font-family: 'Segoe UI', sans-serif;
      max-width: 900px;
      margin: 0 auto;
      padding: 20px;
      background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
      min-height: 100vh;
      color: #eee;
    }
    header {
      text-align: center;
      border-bottom: 2px solid #c9a227;
      padding-bottom: 20px;
    }
    h1 { color: #c9a227; }
    h2 { color: #c9a227; }
    .info-panel, .demo-panel {
      background: rgba(255,255,255,0.05);
      border: 1px solid #c9a227;
      border-radius: 8px;
      padding: 20px;
      margin: 20px 0;
    }
    ul { list-style: none; padding: 0; }
    li::before { content: "» "; }
  `]
})
export class AppComponent {}

Widzisz błąd w tej lekcji?

Sprawdź się

Odpowiedz na pytania z tej lekcji. Wybierz odpowiedź, a od razu zobaczysz, czy jest poprawna.

  1. 1. Co umieszczamy w właściwości 'declarations' dekoratora @NgModule?

  2. 2. Która właściwość @NgModule wskazuje główny komponent startowy aplikacji i występuje tylko w AppModule?

To 2 z 5 pytań do tej lekcji. Pozostałe rozwiążesz w grze.

Zadania praktyczne w grze

  • Układanie w poziomie

    Ułóż tokeny jednej linii importu dekoratora NgModule z @angular/core:

  • Edytor kodu

    Uzupełnij dekorator @NgModule dla modułu SamuraiModule z komponentami SamuraiListComponent i SamuraiCardComponent.

  • Klikanie w kolejności

    Kliknij elementy w kolejności, aby zbudować początek dekoratora: @NgModule({

  • Układanie w pionie

    Uporządkuj właściwości wewnątrz dekoratora @NgModule zgodnie z typowym zapisem (kolejne linie od góry):

Przydatne artykuły