Co jest w tym projekcie
ng new utworzył kilkadziesiąt plików. W codziennej pracy dotykasz kilku z nich. Zobaczysz drogę od wpisania adresu do pojawienia się napisu na ekranie — i będziesz wiedzieć, w którym pliku co wpisać.
Czego się dziś nauczysz
- Wskażesz pliki, które edytujesz, i te, których nie ruszasz.
- Opiszesz cztery kroki od wpisania
localhost:4200do pojawienia się strony. - Wskażesz w
index.htmlmiejsce, w które Angular wstawia aplikację. - Powiesz, co robią
selector,templateUrliimportsw dekoratorze@Component. - Uporządkujesz plik
app.tstak, żeby zniknęło ostrzeżenie NG8113 z lekcji 01. - Wskażesz plik z ustawieniami całej aplikacji.
- Odczytasz komunikat błędu i znajdziesz plik, którego dotyczy.
Przygotowanie: lekcja 01 — masz projekt klub-gier, który się uruchamia. Przewidywany czas: 45 min z zadaniami.
Które pliki są Twoje
Folder projektu wygląda groźnie, ale większość to rzeczy, których nie ruszasz. Twoja praca odbywa się w folderze src, a w nim prawie wyłącznie w src/app.
| Plik lub folder | Do czego służy | Edytujesz? |
|---|---|---|
src/app/app.html | szablon — to, co widać na ekranie | ciągle |
src/app/app.ts | klasa komponentu — dane i metody | ciągle |
src/app/app.css | style tylko tego komponentu | czasem |
src/app/app.config.ts | ustawienia całej aplikacji | rzadko |
src/app/app.routes.ts | lista podstron (adresów) | od lekcji 34 |
src/app/app.spec.ts | testy jednostkowe | nie w tym kursie |
src/index.html | jedyna strona HTML aplikacji | raz — tytuł i język |
src/main.ts | plik startowy | prawie nigdy |
src/styles.css | style wspólne dla całej aplikacji | czasem |
public/ | obrazki i pliki podawane bez zmian | od lekcji 07 |
angular.json, package.json | konfiguracja projektu i lista bibliotek | rzadko (lekcja 03) |
node_modules/ | pobrane biblioteki | nigdy — odtwarza go npm install |
Zasada na cały kurs
Plik .ts to dane i decyzje, plik .html to wygląd. Gdy nie wiesz, gdzie coś wpisać, zapytaj siebie: „czy to widać na ekranie?”. Jeśli tak — szablon. Jeśli to liczba do policzenia albo wartość do zapamiętania — klasa.
Droga od adresu do ekranu
Kiedy wpisujesz localhost:4200, zawsze dzieją się cztery rzeczy, w tej samej kolejności:
- Przeglądarka dostaje
index.html. W środku jest pusty znacznik<app-root>. - Uruchamia się
main.tsi wołabootstrapApplication(App, appConfig). - Angular szuka w stronie znacznika, który pasuje do
selectorkomponentuApp— czyli<app-root>. - W to miejsce wstawia szablon
app.htmlz danymi z klasyApp.
Komponent to para: klasa w pliku .ts i szablon w pliku .html. Łączy je dekorator @Component({ ... }) — zapis z małpą tuż nad klasą, który mówi Angularowi: „ta klasa jest komponentem, a oto jego ustawienia”.
| Ustawienie | Znaczenie |
|---|---|
selector | nazwa znacznika, pod którą komponent da się wstawić na stronę |
templateUrl | ścieżka do pliku z szablonem |
styleUrl | ścieżka do pliku ze stylami komponentu |
imports | lista rzeczy, których szablon używa (innych komponentów — lekcja 04) |
Strona, która przychodzi do przeglądarki
Cała aplikacja Angulara mieści się w jednym pliku HTML. Otwórz go i zmień dwie rzeczy: język strony na polski i tytuł na karcie przeglądarki.
<!doctype html>
<html lang="pl">
<head>
<meta charset="utf-8">
<title>Klub gier</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root></app-root>
</body>
</html>
Karta przeglądarki: Klub gier
W body nie ma żadnej treści — jest jeden znacznik <app-root>, którego nie zna żadna przeglądarka. Tutaj Angular wstawi Twoją aplikację. lang="pl" mówi przeglądarce, że strona jest po polsku (przydaje się czytnikom ekranu i tłumaczowi).
Zatrzymaj się
Gdybyś wpisał tekst między <app-root> a </app-root>, byłby widoczny tylko przez ułamek sekundy. Dlaczego akurat przez chwilę? Sprawdzisz to w zadaniu 3.
Kto to wszystko uruchamia
Jeden plik startowy, kilka wierszy. To on łączy stronę z Twoim kodem.
import { bootstrapApplication } from '@angular/platform-browser';
import { appConfig } from './app/app.config';
import { App } from './app/app';
bootstrapApplication(App, appConfig)
.catch((err) => console.error(err));
import { App } from './app/app';— weź klasęAppz plikusrc/app/app.ts(rozszerzenia.tssię nie pisze).bootstrapApplication(App, appConfig)— uruchom aplikację: pierwszy argument to komponent główny, drugi — ustawienia..catch(...)— jeśli start się nie uda, wypisz błąd w konsoli przeglądarki (F12 → Console).
Zatrzymaj się
Ten plik wskazuje na klasę App, ale nigdzie nie pisze app-root. Skąd Angular wie, do którego znacznika ma wstawić komponent? Odpowiedź jest w następnym przykładzie.
Komponent to para plików
CLI utworzyło app.ts przygotowany pod stronę powitalną. Po lekcji 01 strony powitalnej już nie ma, więc uporządkuj klasę: usuń import RouterOutlet i pole title, a dopisz własne pole tytul.
import { Component } from '@angular/core';
@Component({
imports: [],
selector: 'app-root',
styleUrl: './app.css',
templateUrl: './app.html',
})
export class App {
readonly tytul = 'Klub gier';
}
<h1>{{ tytul }}</h1>
<p>Tu wkrótce pojawi się lista wydarzeń.</p>
Klub gier
Tu wkrótce pojawi się lista wydarzeń.
Ostrzeżenie NG8113 zniknęło z terminala — tablica imports jest pusta, bo szablon nie używa żadnego dodatkowego elementu. selector: 'app-root' mówi: „jestem znacznikiem app-root” — dlatego aplikacja ląduje właśnie w tym miejscu index.html.
Zapis {{ tytul }} w szablonie wstawia wartość pola tytul z klasy. To zapowiedź lekcji 05, gdzie poznasz go dokładnie — dziś wystarczy zauważyć, że szablon widzi pola swojej klasy. Słowo readonly oznacza, że pola nie da się później zmienić (znasz je z TypeScriptu).
Zatrzymaj się
Zmień w app.ts selektor na app-korzen i zapisz. Kompilacja się uda, ale strona będzie pusta. Naciśnij F12 i przeczytaj błąd w zakładce Console — mówi, że selektor nie pasuje do żadnego elementu. Przywróć app-root.
Ustawienia całej aplikacji
Wszystko, co dotyczy aplikacji jako całości, a nie jednego komponentu, trafia do app.config.ts. Na razie tylko go oglądasz.
import { ApplicationConfig, provideBrowserGlobalErrorListeners } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
export const appConfig: ApplicationConfig = {
providers: [
provideBrowserGlobalErrorListeners(),
provideRouter(routes)
]
};
import { Routes } from '@angular/router';
export const routes: Routes = [];
Tablica providers to lista „usług” włączonych dla całej aplikacji. Dziś są dwie: przechwytywanie błędów w przeglądarce i router — na razie z pustą listą podstron. Ta lista będzie rosła: w lekcji 16 dojdą polskie formaty dat i walut, w lekcji 34 podstrony, w lekcji 36 pobieranie danych z serwera.
Czego tu nie ma
W starszych materiałach zobaczysz w tym pliku provideZoneChangeDetection() albo provideZonelessChangeDetection(). Angular 22 działa domyślnie bez biblioteki zone.js (tryb zoneless), więc żaden z tych wpisów nie jest potrzebny. Co to zmienia — zobaczysz w lekcji 09.
Zatrzymaj się
app.config.ts i app.routes.ts są połączone importem. Znajdź wiersz, który je łączy, i powiedz, która nazwa jest w nim wspólna.
Zestawienie elementów
| Element | Znaczenie | Uwagi |
|---|---|---|
<app-root> | miejsce na aplikację w index.html | Treść w środku zostanie zastąpiona. |
bootstrapApplication(App, appConfig) | uruchomienie aplikacji | W main.ts; nie zmieniasz. |
@Component({ ... }) | dekorator — klasa staje się komponentem | Stoi tuż nad export class. |
selector | nazwa znacznika komponentu | Musi zgadzać się ze znacznikiem w HTML. |
templateUrl | plik szablonu | Literówka = błąd NG2008. |
styleUrl | plik stylów komponentu | Style działają tylko w tym komponencie. |
imports: [] | czego używa szablon | Niewykorzystany wpis = ostrzeżenie NG8113. |
export class App | klasa komponentu | Bez export inne pliki jej nie widzą. |
readonly pole = wartość | pole klasy, którego nie zmienisz | Szablon może je wyświetlić (lekcja 05). |
appConfig.providers | ustawienia całej aplikacji | Rośnie w lekcjach 16, 34, 36. |
routes | lista podstron | Pusta do lekcji 34. |
| F12 → Console | błędy zgłaszane w przeglądarce | Część błędów widać tylko tutaj, nie w terminalu. |
Zanim utkniesz
| Co widzisz | Przyczyna i naprawa |
|---|---|
| Strona pusta, terminal bez błędu, w konsoli przeglądarki The selector „app-korzen” did not match any elements | Selektor w @Component nie zgadza się ze znacznikiem w index.html. |
| NG2008: Could not find template file ’./app.htm’ | Literówka w templateUrl albo plik leży w innym folderze niż klasa. |
| TS2459: Module ’./app/app’ declares 'App’ locally, but it is not exported | Usunięte słowo export przed class App. |
| TS2305: Module ’./app/app’ has no exported member 'Ap’ | Literówka w nazwie klasy w import { ... }. |
| NG8113: All imports are unused | W imports został element, którego szablon nie używa. Usuń go z tablicy i z importu na górze pliku. |
Zmiana w index.html między <app-root> a </app-root> nic nie daje | Angular nadpisuje zawartość <app-root>. Treść wpisuj w szablonie komponentu. |
Edycja w node_modules znika | Ten folder odtwarza npm install. Nigdy go nie edytuj. |
Zadania
Zmień tytuł widoczny na karcie przeglądarki na Klub gier — 4TP (wpisz swoją klasę) i ustaw język strony na polski.
Kryterium sukcesu: karta przeglądarki pokazuje nowy tekst, a w <html> jest lang="pl".
Podpowiedź
To nie jest plik komponentu, tylko jedyna strona HTML aplikacji.
Na początku app.html dopisz komentarz HTML (<!-- ... -->), a w nim sześć wierszy w formacie plik — do czego służy dla plików: index.html, main.ts, app.ts, app.html, app.config.ts, styles.css. Pisz własnymi słowami.
Kryterium sukcesu: komentarz nie jest widoczny na stronie, a każdy z sześciu plików ma jednozdaniowy opis.
Podpowiedź
Komentarz może mieć wiele wierszy — zaczyna się <!--, kończy -->.
W index.html wpisz między <app-root> a </app-root> tekst Ładowanie klubu…. Otwórz narzędzia przeglądarki (F12), zakładkę Network, zaznacz Disable cache, a z listy No throttling wybierz Slow 4G. Odśwież stronę i obserwuj. Zapisz w zeszycie, kiedy tekst znika i dlaczego. Na koniec przywróć No throttling.
Kryterium sukcesu: widzisz napis przez chwilę przed pojawieniem się aplikacji i potrafisz wyjaśnić, który krok z „drogi od adresu do ekranu” go usuwa.
Podpowiedź
Napis jest w pliku, który przychodzi pierwszy. Znika w kroku, w którym Angular wstawia szablon.
Zmień selektor komponentu na app-klub, zapisz i opisz, co się stało: co zniknęło ze strony, czy w terminalu pojawił się błąd i co pokazuje konsola przeglądarki. Następnie napraw program na dwa różne sposoby — za każdym razem zmieniając inny plik.
Kryterium sukcesu: potrafisz wymienić oba sposoby naprawy i powiedzieć, który wybrałbyś w prawdziwym projekcie.
Podpowiedź
Selektor i znacznik muszą być takie same. Można poprawić selektor albo znacznik.
Wprowadź po kolei trzy błędy — każdy osobno, po każdym napraw program przed następnym: (a) w app.ts zmień templateUrl na './app.htm'; (b) w main.ts zmień import { App } na import { Ap }; (c) w app.ts usuń słowo export przed class App. Dla każdego zapisz: kod błędu (NG… albo TS…), plik i wiersz wskazany przez terminal oraz jednozdaniowe wyjaśnienie po polsku.
Kryterium sukcesu: tabelka z trzema wierszami, a projekt na koniec kompiluje się bez błędów.
Podpowiedź
Przy (c) błąd wskazuje inny plik niż ten, który zmieniłeś — to normalne. Plik, w którym zrobiłeś zmianę, jest „przyczyną”, a plik wskazany przez kompilator — „miejscem, gdzie problem wyszedł na jaw”.
Opiekun klubu przysłał listę życzeń: (1) inna nazwa na karcie przeglądarki, (2) zmiana nagłówka „Klub gier” na „Klub gier ZSMI”, (3) szare tło całej strony, (4) dodatkowy akapit z godzinami otwarcia, (5) osobna podstrona „Kontakt”, (6) nowa ikonka strony. Przy każdym punkcie zapisz w zeszycie plik (albo folder), w którym trzeba wprowadzić zmianę. Następnie wykonaj punkty 1, 2 i 4 — punkt 2 przez zmianę wartości pola w klasie, a nie tekstu w szablonie.
Kryterium sukcesu: sześć przyporządkowań plików i trzy wykonane zmiany widoczne w przeglądarce.
Podpowiedź
Skorzystaj z tabeli „Które pliki są Twoje”. Styl dla całej strony to inny plik niż styl komponentu.
Co trzeba zapamiętać
- Pracujesz w
src/app;node_modulesnigdy nie edytujesz. index.htmlzawiera pusty<app-root>— tam trafia aplikacja.main.tsuruchamia aplikację i wskazuje komponent głównyApp.- Komponent to klasa
.tsi szablon.html, połączone dekoratorem@Component. selectorto nazwa znacznika komponentu; musi zgadzać się z HTML-em.- Niepotrzebny wpis w
importsdaje ostrzeżenie NG8113. - Ustawienia całej aplikacji mieszkają w
app.config.ts. - Kod błędu i ścieżka pliku w terminalu prowadzą prosto do miejsca problemu; część błędów widać tylko w konsoli przeglądarki (F12).
Sprawdź się: gdzie wpiszesz nowy tekst do pokazania użytkownikowi, a gdzie wartość, którą program ma zapamiętać?
Dokumentacja: angular.dev — struktura projektu.