Čisté funkce v šablonách Angular 21.2: Možnosti a omezení
Od verze 21.2 umožňuje Angular používat čisté JavaScriptové funkce přímo v HTML šablonách bez nutnosti deklarovat metody ve třídě komponenty. Toto zjednodušuje zpracování dat, jako je filtrování polí nebo výpočty na základě signálů, ale vyžaduje striktní dodržování pravidel čistoty funkcí.
Uvažujme komponentu se seznamem hrdinů, kde jsou data uložena v signálu heroes typu WritableSignal<Hero[]>:
import { Component, signal, WritableSignal } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HeroesList } from '../heroes-list/heroes-list';
export interface Hero {
id: number;
name: string;
lastName: string;
nickname: string;
email: string;
}
@Component({
selector: 'app-heroes',
imports: [HeroesList, CommonModule],
templateUrl: './heroes.component.html',
styleUrl: './heroes.component.scss',
standalone: true
})
export class HeroesComponent {
heroes: WritableSignal<Hero[]> = signal<Hero[]>([
// data hrdinů
]);
selectedHeroId: WritableSignal<number> = signal<number>(1);
}
Základní výpis seznamu pomocí @for:
<ul>
@for (hero of heroes(); track $index) {
<li>{{ `${hero.name} ${hero.lastName} - ${hero.email}` }}</li>
}
</ul>
Navigace seznamem bez metod komponenty
Aktualizace signálu selectedHeroId se nyní provádí inline v obslužných rutinách kliknutí. Namísto metod prevHero() a nextHero() se používá update() s lambda funkcí:
<div class="hero-navigation">
<button (click)="selectedHeroId.update(count => count === 1 ? heroes().length : count - 1)">Zpět</button>
<div class="hero-name">
{{ heroes()[selectedHeroId() - 1].name + ' ' + heroes()[selectedHeroId() - 1].lastName }}
</div>
<button (click)="selectedHeroId.update(count => count === heroes().length ? 1 : count + 1)">Vpřed</button>
</div>
<div class="hero-info">
{{ heroes()[selectedHeroId() - 1] | json }}
</div>
Toto snižuje množství boilerplate kódu, ale logika cyklické navigace (návrat k prvnímu prvku) zůstává v šabloně.
Filtrování a vyhledávání v šablonách
Filtrování hrdinů podle shody prvních písmen jména a příjmení:
<div>
{{ heroes().filter(hero => hero.name.charAt(0).toLowerCase() === hero.lastName.charAt(0).toLowerCase())
.map(hero => `${hero.name} ${hero.lastName}`).join(', ') }}
</div>
Výsledek: Peter Parker, Stephen Strange, Bruce Banner.
Vyhledávání podle domény emailu:
<div>
{{ heroes().find(hero => hero.email.endsWith('stark.com'))?.name }}
</div>
Výstup: Tony.
Předávání funkcí jako input do podřízených komponent
Podřízená komponenta HeroesList přijímá řadicí funkci přes input:
@Component({
selector: 'app-heroes-list',
template: `
<ul>
@for (hero of sortedHeroes(); track $index;) {
<li>{{ hero.name + ' ' + hero.lastName }}</li>
}
</ul>
`,
standalone: true
})
export class HeroesList {
heroes: InputSignal<Hero[]> = input.required<Hero[]>();
sortFn: InputSignal<(a: Hero, b: Hero) => number> = input.required<(a: Hero, b: Hero) => number>();
sortedHeroes: Signal<Hero[]> = computed(() => [...this.heroes()].sort(this.sortFn()));
}
Použití v nadřazené šabloně:
<app-heroes-list [heroes]="heroes()" [sortFn]="(a, b) => a.name.localeCompare(b.name)"></app-heroes-list>
Řazení podle jména: Bruce Banner, Natasha Romanoff, Peter Parker, Stephen Strange, Tony Stark.
Objekty a literály ve funkcích
Pro vrácení objektů se funkce obalí do kulatých závorek, aby se odlišila od těla funkce:
<ul>
@for (hero of heroes().map(item => ({ name: 'Super ' + item.nickname, email: item.email })); track $index) {
<li>{{ `${hero.name} - ${hero.email}` }}</li>
}
</ul>
Výsledek: Super Spider man - [email protected] atd.
Omezení čistých funkcí
- Víceřádkové funkce nejsou podporovány:
```html
{{ heroes().map(item => { return { name: 'Super ' + item.nickname, email: item.email } }) }}
```
Kompilátor vyhodí chybu.
- Funkce vracející funkce se kompilují jako text:
```html
{{ () => heroes().find(hero => hero.email.endsWith('stark.com'))?.name }}
```
- Pipy uvnitř funkcí jsou zakázány, protože to není čistý JS:
```html
{{ heroes().find(hero => hero.email.endsWith('StaRk.com' | lowercase))?.name }}
```
Přípustné je použití pipy na výsledek:
```html
{{ heroes().find(hero => hero.email.endsWith('stark.com'))?.name | uppercase }}
```
Výsledek: TONY.
Co je důležité
- Čisté funkce v šablonách Angular 21.2 jsou vhodné pro jednoduché operace se signály: filtrování, vyhledávání, aktualizace hodnot.
- Povinné použití kulatých závorek pro objektové literály a zákaz víceřádkových výrazů.
- Předávání funkcí přes input-signal umožňuje zachovat reaktivitu v podřízených komponentách.
- Vyhýbat se pipám uvnitř funkcí; aplikovat je pouze na výsledky.
- Výkon: čisté funkce se přepočítávají při každé detekci změn, pro složitou logiku jsou preferovány computed nebo pipy.
— Editorial Team
Zatím žádné komentáře.