Przejdź do treści
School IT / Przestrzeń do nauki

Interpolacja {{ }} — dane z klasy na ekranie

Dane leżą w klasie, a użytkownik patrzy na szablon. Poznasz najprostszy most między nimi: podwójne klamry. Zobaczysz, co wolno w nie wpisać, czego nie wolno i jak odczytać komunikat, gdy przesadzisz.

Angular 22 {{ }} pola klasy wyrażenia metody operator ?: 45 min
CEL LEKCJI

Czego się dziś nauczysz

  • Pokażesz w szablonie wartość pola klasy za pomocą {{ }}.
  • Wyjaśnisz, dlaczego w szablonie nie piszemy this.
  • Umieścisz w klamrach obliczenie, wywołanie metody i metodę tekstu, np. toUpperCase().
  • Wybierzesz jeden z dwóch napisów operatorem warunek ? a : b.
  • Sformatujesz liczbę do dwóch miejsc po przecinku metodą toFixed(2).
  • Rozpoznasz zapisy, których Angular w klamrach nie przyjmie, i odczytasz komunikat błędu.
  • Odróżnisz błąd kompilacji od ostrzeżenia NG8117 przy metodzie bez nawiasów.

Przygotowanie: lekcje 01–04 — masz projekt z Bootstrapem i umiesz uruchomić przykład przez komponent Demo. Przewidywany czas: 45 min z zadaniami.

TEORIA

Skąd szablon bierze dane

Do tej pory wpisywałeś teksty wprost w HTML. Działa, dopóki nic się nie zmienia. Ale nazwa wydarzenia, liczba wolnych miejsc czy cena biletu będą się zmieniać — i nie chcesz przy każdej zmianie szukać ich w dziesięciu miejscach szablonu.

Dlatego dane trzymamy w klasie komponentu, a w szablonie zostawiamy tylko miejsce, w które Angular je wstawi. To miejsce oznaczamy podwójnymi klamrami — to interpolacja.

szablon — schemat
<p>Tekst stały {{ wyrażenie }} dalszy tekst stały</p>

Angular oblicza to, co stoi między klamrami, zamienia wynik na tekst i wstawia go w to miejsce. Gdy wartość pola się zmieni, napis na ekranie zmieni się razem z nią.

TEORIA

Co wolno w klamrach, a czego nie

Klamry służą do pokazywania. Wolno w nich odczytać wartość i coś policzyć. Zmienianie danych to zadanie metod w klasie.

Zapis w klamrachWolno?Uwagi
{{ nazwa }}takpole klasy, bez this
{{ cena * sztuki }}takdziałania arytmetyczne
{{ razem() }}takwywołanie metody — zawsze z nawiasami
{{ imie.toUpperCase() }}, {{ imie.length }}takmetody i właściwości tekstu znane z TypeScriptu
{{ cena.toFixed(2) }}takliczba z dwoma miejscami po kropce
{{ wolne > 0 ? 'są miejsca' : 'brak' }}takoperator warunkowy wybiera jeden z dwóch wyników
{{ licznik = 5 }}, {{ licznik++ }}nieprzypisanie — błąd NG5002
{{ if (x) { } }}nieinstrukcje nie są wyrażeniami (warunki w szablonie: lekcja 12)
{{ Math.round(cena) }}nieszablon widzi tylko składowe swojej klasy, nie obiekty globalne

Bez this

W metodach klasy piszesz this.nazwa. W szablonie — samo nazwa: Angular wie, że chodzi o ten komponent. Zapis {{ this.nazwa }} też się skompiluje, ale nikt go tak nie pisze, więc i my nie będziemy.

Metoda potrzebuje nawiasów

{{ razem() }} pokaże wynik. {{ razem }} pokaże na ekranie… treść funkcji jako tekst. To nie jest błąd kompilacji — terminal pokaże tylko żółte ostrzeżenie NG8117, dlatego tak łatwo je przeoczyć.

Operator warunkowy ?:

Zapis warunek ? a : b znasz z TypeScriptu: jeśli warunek jest prawdziwy, wynikiem jest a, w przeciwnym razie b. To wyrażenie, więc wolno go użyć w klamrach. Przy jednym wyborze z dwóch jest czytelny; przy trzech i więcej możliwościach przenieś decyzję do metody w klasie.

PRZYKŁAD 1

Pole klasy na ekranie

Klasa przechowuje dane, szablon je pokazuje. Klamry łączą jedno z drugim — także w środku zdania.

src/app/nowa-05-1/demo.ts — pełny plik
import { Component } from '@angular/core';

@Component({
    selector: 'app-demo',
    imports: [],
    templateUrl: './demo.html'
})
export class Demo {
    readonly nazwa = 'Turniej retro';
    readonly sala = 12;
    readonly wolneMiejsca = 2;
}
src/app/nowa-05-1/demo.html — pełny plik
<div class="card p-3 m-3" style="width: 22rem">
  <h5>{{ nazwa }}</h5>
  <p>Sala {{ sala }}, wolne miejsca: {{ wolneMiejsca }}</p>
</div>
wynik w przeglądarce
Turniej retro
Sala 12, wolne miejsca: 2

Pola są readonly, bo w tej lekcji tylko je pokazujemy. Zmień wartość sala w pliku .ts i zapisz — ekran zmieni się sam.

Zatrzymaj się

W szablonie nie ma słowa this, choć w metodzie klasy napisałbyś this.nazwa. Skąd szablon wie, której klasy pola ma szukać?

PRZYKŁAD 2

W klamrach może być wyrażenie

Między klamrami nie musi stać sama nazwa pola. Może tam być obliczenie, wywołanie metody klasy albo metoda tekstu. Lista to klasy Bootstrapa list-group i list-group-item — każdy element w osobnym wierszu z ramką.

src/app/nowa-05-2/demo.ts — pełny plik
import { Component } from '@angular/core';

@Component({
    selector: 'app-demo',
    imports: [],
    templateUrl: './demo.html'
})
export class Demo {
    readonly cena = 12.5;
    readonly sztuki = 3;
    readonly imie = 'ala';

    razem(): number {
        return this.cena * this.sztuki;
    }
}
src/app/nowa-05-2/demo.html — pełny plik
<ul class="list-group m-3" style="width: 22rem">
  <li class="list-group-item">Cena: {{ cena }} zł</li>
  <li class="list-group-item">Sztuk: {{ sztuki }}</li>
  <li class="list-group-item">Razem: {{ cena * sztuki }} zł</li>
  <li class="list-group-item">Razem z metody: {{ razem() }} zł</li>
  <li class="list-group-item">Wielkimi literami: {{ imie.toUpperCase() }}</li>
  <li class="list-group-item">Długość imienia: {{ imie.length }}</li>
</ul>
wynik w przeglądarce
Cena: 12.5 zł
Sztuk: 3
Razem: 37.5 zł
Razem z metody: 37.5 zł
Wielkimi literami: ALA
Długość imienia: 3

Trzeci i czwarty wiersz dają to samo — raz policzone w szablonie, raz w metodzie. Liczby mają kropkę zamiast przecinka, bo to zapis JavaScriptu; polski format poznasz w lekcji 16.

Zatrzymaj się

Skoro obie drogi dają ten sam wynik, po co komu metoda? Wyobraź sobie, że wzór trzeba zmienić, a stoi w pięciu miejscach szablonu.

PRZYKŁAD 3

Czego w klamrach nie wolno

Interpolacja pokazuje wartość, ale jej nie zmienia. Zacznij od wersji poprawnej, a potem po kolei wklejaj zapisy błędne i czytaj komunikaty.

src/app/nowa-05-3/demo.ts — pełny plik
import { Component } from '@angular/core';

@Component({
    selector: 'app-demo',
    imports: [],
    templateUrl: './demo.html'
})
export class Demo {
    licznik = 0;
    readonly teraz = new Date();
}
src/app/nowa-05-3/demo.html — pełny plik
<div class="p-3">
  <p>Poprawnie: {{ licznik }}</p>
  <p>Też poprawnie: {{ licznik + 1 }}</p>
  <p>Data działa, ale wygląda brzydko: {{ teraz }}</p>
</div>
tak NIE wolno — dopisuj po jednym wierszu, czytaj błąd i usuwaj
<p>{{ licznik = 5 }}</p>
<p>{{ licznik++ }}</p>
<p>{{ Math.round(licznik) }}</p>
komunikaty w terminalu (skrócone)
✘ [ERROR] NG5002: Parser Error: Bindings cannot contain assignments at column 12 in [ licznik = 5 ]
✘ [ERROR] NG5002: Parser Error: Unexpected end of expression:  licznik++
✘ [ERROR] TS2339: Property 'Math' does not exist on type 'Demo'.

Każdy komunikat podaje plik i wiersz. Bindings cannot contain assignments znaczy dosłownie „wiązania nie mogą zawierać przypisań”. Property 'Math’ does not exist on type 'Demo’ — szablon szuka Math w klasie Demo i go nie znajduje.

Zatrzymaj się

Data wypisuje się w długiej, angielskiej postaci, np. Wed Oct 07 2026 14:30:00 GMT+0200. Zapamiętaj to — w lekcji 16 poprawimy ją jednym słowem.

PRZYKŁAD 4

Wybór napisu i ładna cena

Dwa wyrażenia, które w tym kursie zobaczysz setki razy: operator ?:, który wybiera napis, i toFixed(2), który pokazuje cenę z groszami.

src/app/nowa-05-4/demo.ts — pełny plik
import { Component } from '@angular/core';

@Component({
    selector: 'app-demo',
    imports: [],
    templateUrl: './demo.html'
})
export class Demo {
    readonly nazwa = 'Warsztat druku 3D';
    readonly cena = 15;
    readonly wolneMiejsca = 0;

    opis(): string {
        return this.nazwa + ' — ' + this.cena.toFixed(2) + ' zł';
    }
}
src/app/nowa-05-4/demo.html — pełny plik
<div class="card p-3 m-3" style="width: 24rem">
  <h5>{{ nazwa }}</h5>
  <p class="mb-1">Cena: {{ cena.toFixed(2) }} zł</p>
  <p class="mb-1">Status: {{ wolneMiejsca > 0 ? 'są wolne miejsca' : 'brak miejsc' }}</p>
  <p class="mb-1">Liter w nazwie: {{ nazwa.length }}</p>
  <p class="mb-0 text-muted">{{ opis() }}</p>
</div>
wynik w przeglądarce
Warsztat druku 3D
Cena: 15.00 zł
Status: brak miejsc
Liter w nazwie: 17
Warsztat druku 3D — 15.00 zł

15 zamienia się w 15.00, bo toFixed(2) zawsze dopisuje dwa miejsca po kropce. Zmień wolneMiejsca na 4 i zapisz — status zmieni się na „są wolne miejsca”. Metoda opis() składa tekst z kilku pól — w klasie, więc szablon zostaje krótki.

Zatrzymaj się

Usuń nawiasy w {{ opis() }}, zostawiając {{ opis }}. Co pokazała przeglądarka i jaki kod ma żółte ostrzeżenie w terminalu? Przywróć nawiasy.

ELEMENTY WBUDOWANE

Zestawienie elementów

ElementZnaczenieUwagi
{{ pole }}wartość pola na ekranieBez this.
{{ a * b }}wynik obliczeniaKrótkie obliczenia; dłuższe do metody.
{{ metoda() }}wynik metody klasyBez nawiasów — ostrzeżenie NG8117.
tekst.toUpperCase()tekst wielkimi literamitoLowerCase() — małymi.
tekst.lengthliczba znakówWłaściwość, bez nawiasów.
liczba.toFixed(2)liczba jako tekst z 2 miejscami po kropceZaokrągla: (2.345).toFixed(2) → 2.35.
warunek ? a : bjeden z dwóch wynikówWięcej przypadków — metoda w klasie.
readonlypole, którego nie zmieniszDo danych tylko do pokazania.
list-group, list-group-itemlista Bootstrapa z ramkamiNa ul i li.
NG5002błąd składni w szablonieNp. przypisanie w klamrach.
TS2339nie ma takiej składowejLiterówka albo obiekt spoza klasy.
NG8117metoda bez nawiasówOstrzeżenie, nie błąd.
CZĘSTE BŁĘDY

Zanim utkniesz

ZapisProblem
{{ razem }} zamiast {{ razem() }}Na ekranie treść funkcji zamiast liczby, w terminalu tylko ostrzeżenie NG8117. Najczęstsza pomyłka w całym kursie.
{{ licznik = 5 }}Błąd NG5002 — przypisanie w interpolacji jest zabronione. Zmiana wartości należy do metod.
{{ Math.round(x) }}TS2339 — szablon nie widzi obiektów globalnych. Zaokrąglij w metodzie klasy.
Literówka w nazwie pola, np. {{ nazwaa }}TS2339 z numerem wiersza — szablony są sprawdzane tak samo jak kod.
{ nazwa } — pojedyncze klamryNa ekranie pojawi się dosłownie { nazwa }. Klamry muszą być podwójne.
{{ cena.toFixed(2) }} przy cenie '12.5' w cudzysłowieTekst nie ma metody toFixed — błąd TS2339. Liczby zapisuj bez cudzysłowu.
Trzy zagnieżdżone ?: w jednych klamrachDziała, ale nikt tego nie przeczyta. Przenieś decyzję do metody z if.
ZADANIA

Zadania

ZAD 1Twoja karta wydarzenia★☆☆

Zrób komponent z kartą Bootstrapa i trzema polami klasy: nazwa wydarzenia, dzień tygodnia i liczba miejsc. Wszystkie trzy pokaż w szablonie — nazwę w nagłówku, pozostałe w jednym zdaniu, np. „Spotykamy się w czwartek, miejsc: 16”.

Kryterium sukcesu: na ekranie widać trzy wartości pobrane z klasy; zmiana pola w pliku .ts zmienia ekran.

Podpowiedź

Zacznij od przykładu 1 i zmień nazwy pól. Wartości w zdaniu wstawiasz klamrami w środku tekstu.

ZAD 2Legitymacja ucznia★☆☆

Zrób kartę „legitymacji” z polami: imie, nazwisko, klasa, rokUrodzenia i rokBiezacy. Pokaż: imię i nazwisko w jednym wierszu, nazwisko dodatkowo wielkimi literami, klasę oraz wiek policzony w szablonie.

Kryterium sukcesu: wiek zgadza się z różnicą lat, a nazwisko w drugim wierszu jest wielkimi literami.

Podpowiedź

{{ rokBiezacy - rokUrodzenia }} oraz {{ nazwisko.toUpperCase() }}.

ZAD 3Cena po rabacie — dwa podejścia★★☆

Dodaj pola cena i rabatProcent. Pokaż cenę przed rabatem, kwotę rabatu i cenę po rabacie, każdą z dwoma miejscami po kropce. Najpierw policz wszystko w szablonie. Potem przenieś obliczenia do metod kwotaRabatu() i poRabacie() i porównaj długość szablonu. Zostaw w pliku wersję z metodami.

Kryterium sukcesu: obie wersje dają te same liczby, np. dla 80 zł i 15% — 12.00 zł rabatu i 68.00 zł po rabacie.

Podpowiedź

Kwota rabatu to cena * rabatProcent / 100. Metoda poRabacie() może wywołać this.kwotaRabatu().

ZAD 4Paragon ze sklepiku★★☆

Zrób paragon jako listę list-group: trzy produkty (np. drożdżówka, sok, kanapka), każdy ma pole z ceną i pole z ilością. W każdym wierszu pokaż nazwę, ilość, cenę jednostkową i wartość pozycji. W ostatnim, pogrubionym wierszu pokaż sumę obliczoną metodą suma(). Wszystkie kwoty z dwoma miejscami po kropce.

Kryterium sukcesu: suma zgadza się z ręcznym rachunkiem, a po zmianie ilości w pliku .ts zmienia się wartość pozycji i suma.

Podpowiedź

Jeśli suma() zwraca liczbę, w szablonie dopisz .toFixed(2): {{ suma().toFixed(2) }}. Pogrubienie — klasa fw-bold.

ZAD 5Ile zostało miejsc★★★

Wydarzenie ma pola limit i zapisani. Pokaż liczbę wolnych miejsc, zajętość w procentach (bez miejsc po przecinku) i komunikat z metody komunikat(): „Zapisy otwarte”, gdy wolnych jest więcej niż 5, „Ostatnie miejsca” przy 1–5 i „Brak miejsc” przy zerze. Sprawdź wszystkie trzy przypadki, zmieniając zapisani.

Kryterium sukcesu: dla limit = 20 i zapisani równego 10, 17 i 20 widać trzy różne komunikaty i zajętość 50%, 85%, 100%.

Podpowiedź

Trzy przypadki to za dużo na ?: — w metodzie użyj if i return. Procent: (zapisani / limit * 100).toFixed(0).

ZAD 6Detektyw błędów★★★

Wklej do szablonu poniższy fragment (pola nazwa, cena, sztuki i metoda razem() są w klasie). Zanim zapiszesz, przewidź w zeszycie, który wiersz da błąd, który ostrzeżenie, a który zadziała. Potem sprawdź, zapisz kody komunikatów i popraw każdy wiersz tak, żeby pokazywał to, co obiecuje.

<p>{{ nazwa.toUppercase() }}</p>
<p>Razem: {{ razem }}</p>
<p>Po zaokrągleniu: {{ Math.round(cena) }}</p>
<p>Dodaj sztukę: {{ sztuki = sztuki + 1 }}</p>
<p>Cena: {{ cena.toFixed(2) }} zł</p>

Kryterium sukcesu: tabelka z pięcioma wierszami (przewidywanie, komunikat, poprawka), a szablon na koniec kompiluje się bez błędów i ostrzeżeń.

Podpowiedź

Jeden wiersz jest poprawny. Wielkość liter w nazwie metody ma znaczenie. Zaokrąglenie przenieś do metody klasy, a „dodaj sztukę” zamień na pokazanie sztuki + 1.

PODSUMOWANIE

Co trzeba zapamiętać

  • {{ pole }} wstawia wartość z klasy do szablonu; w szablonie nie piszemy this.
  • W klamrach może stać obliczenie, metoda klasy albo metoda tekstu czy liczby.
  • Metodę wywołujesz z nawiasami; bez nich zobaczysz treść funkcji i ostrzeżenie NG8117.
  • warunek ? a : b wybiera jeden z dwóch wyników; więcej przypadków — metoda z if.
  • toFixed(2) pokazuje liczbę z dwoma miejscami po kropce.
  • Interpolacja niczego nie zmienia: przypisania dają błąd NG5002.
  • Szablon widzi tylko składowe swojej klasy — Math i inne obiekty globalne nie są dostępne.

Sprawdź się: masz pole cena = 20 i metodę zRabatem(). Co pokaże {{ zRabatem }}, a co {{ zRabatem() }}?

Dokumentacja: angular.dev — wiązanie danych w szablonie.

Postęp zapisuje się w tej przeglądarce.