23 cze 2022
5 min

Angular v14 – Co warto wiedzieć?

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.

@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.

@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.

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).

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. 

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.

// 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 🙂 🙂

Playground

Używanie protected fields w templatce

I na koniec, taki smaczek. Otrzymaliśmy możliwość używania pól oznaczonych jako protected w templatce.

@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:

Najczęściej zadawane pytania

Jak utworzyć standalone component w Angular 14?

Aby utworzyć standalone component w Angular 14, ustaw flagę standalone: true w dekoratorze @Component. Komponent może wtedy w tablicy imports przyjmować inne standalone komponenty oraz całe moduły, np. MatButtonModule, bez konieczności deklarowania go w NgModule. Standalone komponenty mogą też być importowane przez moduły.

Jak lazy loadować komponent w routingu Angular 14 za pomocą loadComponent?

W Angular 14 możesz lazy loadować komponent, używając właściwości loadComponent w definicji route, np. loadComponent: () => import('./admin/panel.component').then(mod => mod.AdminPanelComponent). Rozwiązanie działa wyłącznie wtedy, gdy ładowany komponent jest standalone, czyli ma ustawione standalone: true.

Jak ustawić providers dla konkretnej ścieżki routingu w Angular 14?

Od Angular 14 właściwość providers można zdefiniować bezpośrednio w obiekcie route, co pozwala udostępnić serwisy tylko dla danej ścieżki i jej dzieci. Przykładowo serwis AdminService lub token ADMIN_API_KEY ustawiony w providers route admin będzie dostępny wyłącznie w tej ścieżce oraz w jej children, odpowiadając on providerom z modułów.

Jak ustawić tytuł strony na poziomie routingu w Angular 14?

W Angular 14 tytuł strony ustawisz bezpośrednio w definicji route, używając właściwości title, np. { path: 'home', component: HomeComponent, title: 'My App - Home' }. Wcześniej trzeba było wstrzyknąć serwis Title i ręcznie wywołać jego metodę setTitle(), co wymagało dodatkowego kodu w komponentach.

Czym są typed forms w Angular 14 i jak zmigrować formularze z wersji 13?

Typed forms to typowane FormGroup, FormControl i FormArray, które zapewniają bezpieczeństwo typów wartości kontrolek. Podczas migracji polecenie ng update zamienia dotychczasowe klasy na wersje z prefiksem Untyped, np. UntypedFormGroup i UntypedFormControl, dzięki czemu istniejące formularze nadal działają. Typować można je stopniowo, formularz po formularzu.

Czy można używać pól protected w szablonie Angular 14?

Tak, w Angular 14 pola oznaczone jako protected w klasie komponentu można używać bezpośrednio w templatce, np. {{ message }}. Wcześniej kompilator tego nie akceptował, a zmiana pozwala ograniczyć dostęp do pól tylko do komponentu, nadal udostępniając je widokowi.

Podziel się artykułem

Zapisz się na nasz newsletter

Dołącz do community Angular.love i bądź na bieżąco z trendami.