Dokładnie 2 czerwca, swoją premiera miała najnowsza, czternasta już wersja Angulara. W tym artykule przyjrzymy się najważniejszym zmianom, jakie znajdziecie w ng14. Zapraszam do lektury.
Standalone components
Długo wyczekiwany feature znalazł się w 14 wersji naszego ukochanego frameworka. Z jednej strony jest to odpowiedź na krytykę, z którą framework zmagał się od wielu lat, jako by był on zbyt trudny dla początkujących, a jako jeden z głównych powodów wskazywano angularowe moduły. Z drugiej strony możemy być pewni, że ta zmiana przyniesie nam bardzo dużo nowych usprawnień, ekscytujących sposobów i przykładów wykorzystania tej funkcjonalności.
Od teraz nasze komponenty, dyrektywy oraz pipe’y możemy tworzyć jako standalone, poprzez ustawienie flagi “standalone” na true w ich dekoratorach.
1 2 3 4 5 6 7 8 9 10 11 |
@Component({ standalone: true, selector: 'photo-gallery', imports: [ImageGridComponent, MatButtonModule], template: ` ... <image-grid [images]="imageList"></image-grid> `, }) export class PhotoGalleryComponent { // component logic } |
Jak widać na powyższym przykładzie, analogicznie do modułu, wspomniany dekorator przyjmuje imports, wewnątrz którego mogą znaleźć się inne “standalonowe komponenty” (ImageGridComponent) lub całe moduły (MatButtonModule – tak jak ma to miejsce w przypadku dekoratora modułu). Standalonowe komponenty mogą również być importowane przez moduły.
Wprowadzenie powyższych zmian nie musi dla nas oznaczać całkowitego odejścia od modułów, albowiem zostały one inicjalnie zaimplementowane w Angularze po to, aby pomóc nam organizować aplikacje w spójne bloki funkcjonalne. Nadal możemy natrafić na przykład gdzie zastosowanie modułu może mieć sens. Szczególnie może dotyczyć to bibliotek. Bazując na poniższym przykładzie zarówno ImageCarouselComponent oraz ImageSlideComponent muszą być obecne w templatce, aby zapewnić właściwie działanie karuzeli obrazków, która działa w oparciu o te komponenty.
1 2 3 4 5 |
@NgModule({ imports: [ImageCarouselComponent, ImageSlideComponent], exports: [ImageCarouselComponent, ImageSlideComponent], }) export class CarouselModule {} |
Nie jest to jedyna konsekwencja tej zmiany, wpływa ona również na inne obszary naszej aplikacji, między innymi na routing.
Routing
Mamy możliwość lazy loadowania standalonowych komponentów.
1 2 3 4 |
export const ROUTES: Route[] = [ {path: 'admin', loadComponent: () => import('./admin/panel.component').then(mod => mod.AdminPanelComponent)}, // ... ]; |
Powyższy przykład działa tylko i wyłącznie w przypadku, gdy AdminPanelComponent będzie standalone. To nie koniec zmian w tym obszarze. Wiele wskazuje na to, że nowy sposób podejścia do definiowania routingu, będzie skutkował tym, że może on stać się sercem naszej aplikacji i w wielu przypadkach odpowiadać za to, jakie serwisy będą dostępne dla nas pod danym route’m, ponieważ od teraz również tutaj możemy definiować providery (odpowiednik providers z modułów).
1 2 3 4 5 6 7 8 9 10 11 12 13 |
export const ROUTES: Route[] = [ { path: 'admin', providers: [ AdminService, {provide: ADMIN_API_KEY, useValue: '12345'}, ], children: [ path: 'users', component: AdminUsersComponent, path: 'teams', component: AdminTeamsComponent, ], }, ]; |
AdminService oraz ADMIN_API_KEY będą dostępne tylko dla route ‘admin’ oraz jego dzieci.
Page Title
Otrzymaliśmy również możliwość ustawiania tytułu dla naszych stron na poziomie naszych route’ów. Uprzednio byliśmy zmuszeni ustawiać go manualnie poprzez wstrzyknięcie serwisu Title, a następnie wywołanie metody setTitle(). Od teraz możemy tą wartość ustawiać na poziomie definicji naszego routingu.
1 2 3 4 5 6 7 8 9 |
const routes: Routes = [{ path: 'home', component: HomeComponent title: 'My App - Home' // <-- Page title }, { path: 'about', component: AboutComponent, title: 'My App - About Me' // <-- Page title }]; |
Typed Forms
Kolejny, bardzo długo wyczekiwany feature. Issue dotyczący tej zmiany powstał w 2016 roku! Od teraz możemy typować nasze formularze. Nowe Api zapewni nam pewność, że wartości w naszych kontrolkach, grupach oraz array’ach będą TYPE SAFE. Oprócz tego, że sama zmiana jest świetna, to dodatkowo Angular zadbał o możliwość stopniowej migracji, bez konieczności zamartwiania się o zepsucie dotychczas działających formularzy. Po uruchomieniu ng update, nasz formularz z wersji 13, przyjmie postać przedstawioną na poniższym przykładzie.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// v13 untyped form const cat = new FormGroup({ name: new FormGroup( first: new FormControl('Barb'), last: new FormControl('Smith'), ), lives: new FormControl(9) }); // v14 untyped form after running `ng update` const cat = new UntypedFormGroup({ name: new UntypedFormGroup( first: new UntypedFormControl('Barb'), last: new UntypedFormControl('Smith'), ), lives: new UntypedFormControl(9) }); |
Wszystkie dotychczasowe modele zostaną zmienione na swój odpowiednich utworzony poprzez dodanie prefixu Untyped. Ma to na celu umożliwienie nam stopniowego typowania poszczególnych formularzy i bezpieczną migrację. Co najważniejsze, od teraz możecie oczekiwać poniższych podpowiedzi od swojego IDE podczas pracy z poprawnie zatypowanym formularzem 🙂 🙂
Używanie protected fields w templatce
I na koniec, taki smaczek. Otrzymaliśmy możliwość używania pól oznaczonych jako protected w templatce.
1 2 3 4 5 6 7 |
@Component({ selector: 'my-component', template: '{{ message }}', // Now compiles! }) export class MyComponent { protected message: string = 'Hello world'; } |
Zmian i usprawnień jest więcej. Pełną pulę możecie znaleźć w changelogu oraz na oficjalnym blogu Angulara. Dajcie znać w komentarzach, czy na którąś z tych zmian szczególnie czekaliście! 🙂
Inne wersje
Sprawdź zmiany w innych wersjach Angular:
Fajny artykuł! Wielkie dzięki za podjęty temat.
> Bazując na poniższym przykładzie zarówno ImageCarouselComponent oraz ImageSlideComponent muszą być obecne w templatce, aby zapewnić właściwie działanie karuzeli obrazków, która działa w oparciu tę komponentu.
Druga część zdania – do poprawy 🙂
Dzięki Marcin, poprawione 🙂