Dataczwartek, 13 sierpnia 2026 Czas17:48:09
← Aplikacje webowe

Lekcja 4. Omówienie gotowego małego programu — kalkulator BMI krok po kroku

Średni

Po co się tego uczymy?

Zanim zaczniesz uczyć się każdej technologii osobno i szczegółowo (Node.js, TypeScript, Bootstrap, Angular — kolejne lekcje), zobacz najpierw, jak to wszystko wygląda RAZEM, w praktyce, na przykładzie małego, kompletnego programu — kalkulatora BMI. Nie musisz jeszcze rozumieć każdej linijki — chodzi o to, żebyś zobaczył OGÓLNY OBRAZ i wiedział, gdzie w kolejnych lekcjach szukać wyjaśnienia konkretnego fragmentu.

Teoria

Poniższy przykład to kompletny, mały komponent Angular obliczający BMI (wskaźnik masy ciała) na podstawie wzrostu i wagi wpisanych przez użytkownika. Przejdźmy przez niego fragment po fragmencie — z zapowiedzią, w KTÓREJ kolejnej lekcji poznasz dokładnie dany element.

1. Tworzenie komponentu — polecenie w terminalu. Zanim jakikolwiek kod powstanie, w terminalu Visual Studio (albo w terminalu systemowym w folderze projektu klienckiego) wywołuje się polecenie Angular CLI: ng generate component bmi-calculator --standalone. To polecenie URUCHAMIANE JEST przez Node.js (silnik wykonujący JavaScript poza przeglądarką, pełne omówienie w lekcji 5) — samo ng to skrót od Angular CLI, zainstalowanego wcześniej przez npm (menedżer pakietów Node.js). Efekt: Angular SAM tworzy 3 pliki (.ts, .html, .css) z gotowym szkieletem komponentu.

2. Klasa komponentu — plik .ts. Napisana w języku TypeScript (pełne omówienie w lekcji 6) — to JavaScript rozszerzony o typy (number, string...), które pomagają wychwycić błędy ZANIM program się uruchomi. Klasa BmiCalculatorComponent ma pola (height, weight, bmi) przechowujące dane, i metodę obliczBMI() z logiką obliczeniową — dokładnie ten sam podział na "dane" i "zachowanie", którego uczyłeś się przy klasach w dziale programowania obiektowego.

3. Szablon — plik .html. To WIDOK komponentu — zwykły HTML, ale z rozszerzeniami składni Angulara (pełne omówienie w lekcjach 8-10): [(ngModel)]="height" to dwukierunkowe wiązanie danych (wpisany tekst automatycznie aktualizuje pole height w klasie, i odwrotnie), a (click)="obliczBMI()" to podpięcie zdarzenia kliknięcia do metody z klasy TypeScript.

4. Stylowanie — Bootstrap. Klasy takie jak class="container" czy przyciski ze stylem "ładnego, gotowego wyglądu" (widoczne w pełnych projektach w dalszych lekcjach) pochodzą z biblioteki Bootstrap (pełne omówienie w lekcji 7) — zestawu gotowych stylów CSS, dzięki którym nie trzeba samodzielnie projektować wyglądu każdego przycisku czy formularza od zera.

5. Instalacja zależności — npm. Zanim komponent mógłby korzystać z formularzy Angulara (ngModel), trzeba było wcześniej zainstalować odpowiedni pakiet poleceniem npm install @angular/formsnpm (Node Package Manager, część Node.js) to "sklep" z gotowymi bibliotekami, z którego korzysta niemal każdy projekt JavaScript/TypeScript.

Ten sam wzorzec (komenda CLI → plik .ts z logiką → plik .html z widokiem → stylowanie Bootstrapem) powtórzy się w KAŻDYM kolejnym komponencie, który zbudujesz w tym dziale — łącznie z czterema pełnymi projektami na końcu.

Schemat

Terminal (Node.js + npm + Angular CLI)
        │  ng generate component bmi-calculator --standalone
        ▼
Wygenerowane pliki:
┌────────────────────────────┐
│ bmi-calculator.component.ts │  ← TypeScript: dane (height, weight, bmi)
│                              │     + logika (obliczBMI())          [lekcja 6]
└──────────────┬───────────────┘
               │ templateUrl
               ▼
┌────────────────────────────┐
│ bmi-calculator.component.html │ ← HTML + składnia Angular:
│                                │   [(ngModel)], (click)            [lekcje 8-10]
│                                │   + klasy Bootstrap (stylowanie)  [lekcja 7]
└────────────────────────────────┘

npm install @angular/forms   ← instalacja zależności (npm, część Node.js) [lekcja 5]

Przykład z życia

Dokładnie tak, jak przy nauce nowego dania w kuchni najpierw ogląda się gotowy przepis "od góry do dołu", żeby zobaczyć, z jakich składników i kroków się składa, zanim zacznie się uczyć każdej techniki (siekanie, duszenie, pieczenie) osobno — ta lekcja pokazuje "gotowe danie" (kalkulator BMI), żebyś wiedział, DOKĄD zmierzasz, zanim zaczniesz uczyć się poszczególnych "technik kulinarnych" (Node.js, TypeScript, Bootstrap, Angular) w kolejnych lekcjach.

bmi-calculator.component.html

<!-- bmi-calculator.component.html -->
<div class="container text-center mt-5">
    <h2>Kalkulator BMI</h2>

    <label>Podaj wzrost (cm):</label>
    <input type="number" [(ngModel)]="height" placeholder="np. 180" class="form-control" />

    <label>Podaj wagę (kg):</label>
    <input type="number" [(ngModel)]="weight" placeholder="np. 75" class="form-control" />

    <button (click)="obliczBMI()" class="btn btn-primary mt-3">Oblicz BMI</button>

    <p *ngIf="bmi !== null" class="mt-3">
        Twoje BMI to: <strong>{{ bmi.toFixed(1) }}</strong>
    </p>
</div>

bmi-calculator.component.ts

// bmi-calculator.component.ts
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';

@Component({
  selector: 'app-bmi-calculator',
  standalone: true,
  imports: [CommonModule, FormsModule],
  templateUrl: './bmi-calculator.component.html',
  styleUrls: ['./bmi-calculator.component.css']
})
export class BmiCalculatorComponent {
  height: number = 0;
  weight: number = 0;
  bmi: number | null = null;

  obliczBMI() {
    if (this.height > 0 && this.weight > 0) {
      const heightInMeters = this.height / 100;
      this.bmi = this.weight / (heightInMeters * heightInMeters);
    }
  }
}

Komentarz i wyjaśnienie kodu

imports: [CommonModule, FormsModule] pokazuje ważną cechę nowoczesnego Angulara (komponenty "standalone") — każdy komponent JAWNIE deklaruje, jakich DODATKOWYCH możliwości potrzebuje: CommonModule daje dostęp do dyrektyw takich jak *ngIf (warunkowe pokazywanie fragmentu HTML), a FormsModule daje dostęp do [(ngModel)] (dwukierunkowe wiązanie pól formularza). Bez tych importów odpowiednie znaczniki w HTML po prostu by nie zadziałały.

height: number = 0; i bmi: number | null = null; to przykład składni TypeScript — po dwukropku podana jest DOKŁADNA nazwa typu danych (number), a number | null oznacza "liczba ALBO brak wartości" (podobnie do double? z C#, które poznałeś w dziale MAUI). Ta jedna linijka pokazuje różnicę między TypeScript a zwykłym JavaScript, gdzie takich deklaracji typów by nie było.

*ngIf="bmi !== null" w szablonie HTML to dyrektywa strukturalna Angulara — CAŁY fragment <p> pojawia się w przeglądarce TYLKO wtedy, gdy warunek jest prawdziwy (czyli dopiero po kliknięciu przycisku i obliczeniu wyniku) — analogiczne do @if z lekcji o Razor w innych częściach tego kursu, tylko w składni Angulara.

Ćwiczenie samodzielne

Przepisz (nie kopiuj-wklej, tylko przepisz ręcznie, żeby lepiej zapamiętać składnię) powyższy komponent w nowym projekcie Angular, i uruchom go — sprawdź, że wpisanie wzrostu i wagi, a potem kliknięcie przycisku, poprawnie wylicza i wyświetla BMI.

Zadania do pracy własnej

  1. Znajdź w kodzie WSZYSTKIE miejsca, gdzie występuje składnia specyficzna dla Angulara (nie zwykły HTML/TypeScript) i wypisz je w tabeli z krótkim opisem, co robi każda z nich.

  2. Dodaj do komponentu kategorię BMI (niedowaga/norma/nadwaga/otyłość) jako nowe pole klasy, wyliczane w metodzie obliczBMI(), i wyświetl ją obok liczbowego wyniku w szablonie HTML.

  3. Zainstaluj wymagany pakiet (npm install @angular/forms, jeśli jeszcze nie masz) i rozbuduj przykład o walidację: przycisk "Oblicz BMI" powinien być NIEAKTYWNY ([disabled]), dopóki oba pola (wzrost, waga) nie mają wartości większej od zera.

Typowe błędy

Próba użycia [(ngModel)] bez zaimportowania FormsModule — Angular zgłosi błąd kompilacji, że nie rozpoznaje tego atrybutu; to bardzo częsty błąd na start, bo łatwo zapomnieć o imporcie w standalone components.

Oczekiwanie, że zrozumiesz KAŻDY szczegół już w tej lekcji — to normalne, że wiele elementów (dekorator @Component, *ngIf, [(ngModel)]) jest na razie tylko ZASYGNALIZowanych; pełne wyjaśnienie każdego z nich znajdziesz w konkretnie wskazanej, kolejnej lekcji.

Nawiązanie do egzaminu zawodowego

Ta lekcja daje "mapę drogową" dla całej reszty działu — każdy element pokazany tutaj pobieżnie zostanie dokładnie wyjaśniony w kolejnych lekcjach (5-10), a sam ten kalkulator BMI, w pełnej, rozbudowanej wersji z backendem ASP.NET Core, powróci jako pierwszy z czterech projektów końcowych (lekcja 20).