MediMax

Tworzenie aplikacji Medicos Web w Angular (standalone) w Visual Studio 2022


1. Wymagania wstępne

Zanim zaczniesz, upewnij się, że masz:

NarzędzieCo robiSkąd wziąć
✅ Node.js (LTS)środowisko uruchomieniowe JSnodejs.org
✅ Angular CLItworzenie i uruchamianie aplikacji Angularnpm install -g @angular/cli
✅ Visual Studio 2022środowisko IDEvisualstudio.microsoft.com
✅ Wtyczka „Node.js development”do pracy z Angular w VSInstalator Visual Studio

➡️ Angular to technologia działająca w przeglądarce. Potrzebuje silnika (Node.js), żeby działać lokalnie.
➡️ Angular CLI to narzędzie, które pozwala jednym poleceniem tworzyć projekty, komponenty, serwisy itd.
➡️ Visual Studio 2022 ma narzędzia do programowania – i musi mieć włączony „Node.js development”, żeby obsłużyć Angulara.


2. Utworzenie projektu Angular w Visual Studio

  1. Otwórz Visual Studio 2022
  2. Kliknij: „Utwórz nowy projekt”
  3. Wyszukaj: Angular i wybierz: „ASP.NET Core with Angular”(niech backend sobie będzie, ale go nie ruszamy)
  4. Kliknij Dalej
  5. Nazwij projekt: AngularApps
  6. Kliknij Utwórz
  7. Visual Studio utworzy strukturę:
AngularApps/
├─ Controllers/
├─ ClientApp/      to jest nasz Angular
├─ Program.cs

➡️ Ten szablon tworzy dwa projekty naraz:

  • backend (ASP.NET) – tu nic nie zmieniamy,
  • frontend (Angular) – to jest nasza aplikacja, działa w folderze ClientApp.

    Dlatego cała nasza praca będzie w folderze ClientApp.

3. Przejdź do katalogu Angular i uruchom terminal

Angular nie ma żadnego stylu domyślnego. Jeśli chcemy, żeby przyciski wyglądały jak w profesjonalnych aplikacjach, potrzebujemy Bootstrapa – zestawu gotowych styli CSS. Dodaj bootstrapa do angular.json, by formularze wyglądały schludnie i były lepiej dopasowane do różnych ekranów.

cd angularapps.client. // dokładną ścieżkę sprawdź sam jak jest u ciebie

Uwaga! może być wymagana komenda
Set-ExecutionPolicy RemoteSigned 

  1. W Eksploratorze rozwiązań, kliknij prawym na ClientApp → Otwórz w terminalu
  2. W terminalu (u dołu Visual Studio) wpisz:
npm install bootstrap


A potem dopisz do pliku angular.json → styles:

"styles": [
  "node_modules/bootstrap/dist/css/bootstrap.min.css",
  "src/styles.css"
]

➡️ Projekt Angulara ma specjalny plik (package.json), który mówi: „Ta aplikacja potrzebuje takich bibliotek”.
➡️ npm install pobiera i instaluje te biblioteki – bez tego aplikacja nie działa.

To jak instalowanie części do maszyny przed jej złożeniem.


4. Zainicjuj aplikację standalone

W folderze ClientApp, zmień plik main.ts (znajdziesz go w src/) na:

import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';

bootstrapApplication(AppComponent)
  .catch(err => console.error(err));

Teraz możesz usunąć plik app.module.ts, bo nie będzie już potrzebny.

➡️ W Angularze dawniej wszystko było zarządzane przez plik app.module.ts.
➡️ Ale my korzystamy z nowoczesnego systemu – standalone components, czyli „komponentów samowystarczalnych”.
➡️ Zamiast AppModule, uruchamiamy aplikację przez bootstrapApplication(AppComponent).

Dlatego app.module.ts jest zbędny.


5. Stwórz komponenty

W tym samym terminalu:

ng generate component components/formularz --standalone
ng generate component components/podsumowanie --standalone

Kolejność nie jest kluczowa, ale dobrze zacząć od formularz, bo to on emituje dane do podsumowanie.

➡️ Komponent to część strony – jak „klocek UI”.
➡️ formularz to ekran, na którym wpisujesz dane.
➡️ podsumowanie to ekran z wynikiem.
➡️ –standalone oznacza, że komponent nie potrzebuje modułu (NgModule) i można go używać samodzielnie.


6. Skonfiguruj 

app.component.ts

import { Component } from '@angular/core';
import { FormularzComponent } from './components/formularz/formularz.component';
import { PodsumowanieComponent } from './components/podsumowanie/podsumowanie.component';
import { FormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [
    CommonModule,
    FormsModule,
    FormularzComponent,
    PodsumowanieComponent
  ],
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  wynik: any;

  zapiszWynik(dane: any) {
    this.wynik = dane;
  }
}

➡️ AppComponent to kontroler główny całej aplikacji – jak ramka, która spina wszystko razem.
➡️ Gdy użytkownik kliknie „Pokaż dane”, FormularzComponent wysyła dane do AppComponent.
➡️ AppComponent zapisuje je i przekazuje do PodsumowanieComponent.

To centrum przekaźnikowe: odbiera dane z formularza → przekazuje do wyświetlacza.


app.component.html

<h1>Medicos Web</h1>

<app-formularz (wyslij)="zapiszWynik($event)"></app-formularz>

<app-podsumowanie
  [bmi]="wynik?.bmi"
  [lek]="wynik?.lek"
  [godzina]="wynik?.godzina">
</app-podsumowanie>


formularz.component.ts

import { Component, EventEmitter, Output } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';

@Component({
  selector: 'app-formularz',
  standalone: true,
  imports: [CommonModule, FormsModule],
  templateUrl: './formularz.component.html',
  styleUrls: ['./formularz.component.css']
})
export class FormularzComponent {
  waga: number = 0;
  wzrost: number = 0;
  wiek: number = 0;
  lek: string = '';
  godzina: string = '';

  @Output() wyslij = new EventEmitter<any>();

  submit() {
    const bmi = this.waga / Math.pow(this.wzrost / 100, 2);
    this.wyslij.emit({
      bmi: bmi.toFixed(2),
      lek: this.lek,
      godzina: this.godzina
    });
  }
}

➡️ Formularz to panel, gdzie użytkownik wpisuje dane.
➡️ [ngModel] wiąże dane z polami – Angular sam „zapamiętuje”, co wpisałeś.
➡️ Po kliknięciu przycisku wyliczane jest BMI i emitowany jest obiekt z danymi.

To jak tablica rejestrująca dane wejściowe do maszyny.


formularz.component.html

<div>
  <label>Waga (kg): <input [(ngModel)]="waga" type="number"></label><br>
  <label>Wzrost (cm): <input [(ngModel)]="wzrost" type="number"></label><br>
  <label>Wiek: <input [(ngModel)]="wiek" type="number"></label><br>
  <label>Lek: <input [(ngModel)]="lek" type="text"></label><br>
  <label>Godzina przyjęcia: <input [(ngModel)]="godzina" type="time"></label><br>
  <button (click)="submit()">Pokaż dane</button>
</div>


podsumowanie.component.ts

import { Component, Input } from '@angular/core';
import { CommonModule } from '@angular/common';

@Component({
  selector: 'app-podsumowanie',
  standalone: true,
  imports: [CommonModule],
  templateUrl: './podsumowanie.component.html',
  styleUrls: ['./podsumowanie.component.css']
})
export class PodsumowanieComponent {
  @Input() bmi: string = '';
  @Input() lek: string = '';
  @Input() godzina: string = '';
}

➡️ @Input() pozwala przyjąć dane od AppComponent.
➡️ *ngIf=”bmi” – Angular nie wyświetla niczego, dopóki nie ma danych.
➡️ Dane są pokazane dopiero po kliknięciu „Pokaż dane”.

To jak ekran wyników – pokazuje tylko wtedy, gdy coś otrzyma.


podsumowanie.component.html

<div *ngIf="bmi">
  <h3>Twoje BMI: {{ bmi }}</h3>
  <p>Przypomnienie: Weź lek {{ lek }} o godzinie {{ godzina }}</p>
</div>

Uruchom aplikację

W terminalu wpisz:

ng serve

Wprowadzenie do TypeScript w Angularze (na bazie Medicos)


Co to jest TypeScript?

TypeScript (TS) to nowoczesny język programowania stworzony przez firmę Microsoft.

Jest to rozszerzenie JavaScriptu – dodaje do niego m.in. typowanie, klasy, interfejsy, moduły i podpowiedzi, dzięki czemu programowanie staje się łatwiejsze i bezpieczniejsze.

Porównanie:

  • JavaScript – jak zwykły długopis: działa wszędzie, ale nie podpowiada, czy coś robisz dobrze.
  • TypeScript – jak długopis z korektorem: podpowiada, ostrzega, pomaga.

Dlaczego TypeScript w Angularze?

Angular to framework, który od początku powstał z myślą o TypeScripcie.

Zalety:

  • lepsze błędy (pokazuje błędy zanim uruchomisz aplikację),
  • można przewidzieć, jakie dane przepływają przez aplikację,
  • każdy plik jest „samowystarczalny” i dobrze opisany,
  • idealnie nadaje się do pracy zespołowej i nauki.

Struktura przykładowego pliku TypeScript (komponent Angulara)

import { Component, Input } from '@angular/core';
import { CommonModule } from '@angular/common';

@Component({
  selector: 'app-podsumowanie',
  standalone: true,
  imports: [CommonModule],
  templateUrl: './podsumowanie.component.html',
  styleUrls: ['./podsumowanie.component.css']
})
export class PodsumowanieComponent {
  @Input() bmi: string = '';
  @Input() lek: string = '';
  @Input() godzina: string = '';
}

Co oznaczają podstawowe elementy?

ElementZnaczenie
importPobiera z innego pliku lub biblioteki rzeczy potrzebne w tym pliku
@Component({ ... })Dekorator mówiący: „to jest komponent”
selectorJakiego znacznika HTML używać do wyświetlenia komponentu
standalone: trueKomponent działa samodzielnie bez NgModule
imports: [...]Jakie inne biblioteki potrzebuje ten komponent
export classDeklaracja klasy komponentu (czyli logika zachowania komponentu)
@Input()Pozwala otrzymać dane z zewnętrz (np. od AppComponent)
@Output()Pozwala wysyłać dane na zewnątrz (np. do AppComponent)
EventEmitter<any>()Narzędzie do emitowania danych na zewnątrz
ngModelDwukierunkowe wiązanie danych (input zna wartość zmiennej i odwrotnie)

Najczęściej stosowane instrukcje TypeScript w Angularze

1. Deklaracja zmiennej z typem

let wiek: number = 17;
let imie: string = 'Jan';
let aktywny: boolean = true;

2. Tworzenie klasy z właściwościami

export class Uzytkownik {
  imie: string = '';
  wiek: number = 0;
}

3. Metoda (funkcja) w klasie

submit() {
  console.log('Kliknięto przycisk');
}

4. Wysyłanie danych (EventEmitter)

@Output() wyslij = new EventEmitter<any>();

submit() {
  this.wyslij.emit({ imie: 'Jan', wiek: 25 });
}

5. Odbieranie danych (@Input)

@Input() imie: string = '';

Jak łatwo to zapamiętać?

„Każdy komponent Angulara to:”

  • importy (co potrzebujemy)
  • dekorator (mówi Angularowi, że to komponent)
  • klasa (logika: co ma się stać, jakie dane ma przechowywać)

A dane mogą:

  • przychodzić z zewnątrz przez @Input()
  • wychodzić na zewnątrz przez @Output() i emit()

Praktyczny skrót:

// Formularz wysyła dane:
@Output() wyslij = new EventEmitter<any>();
this.wyslij.emit({ bmi: 22.5 });

// AppComponent odbiera dane:
zapiszWynik(dane) { this.wynik = dane; }

// Podsumowanie pokazuje dane:
@Input() bmi: string = '';

Dzięki TypeScriptowi aplikacja jest:

  • czytelniejsza,
  • mniej podatna na błędy,
  • i bardziej logiczna w przepływie danych – idealna do nauki myślenia obiektowego i komponentowego.