Zpět na domů

Čisté funkce v šablonách Angular 21.2

Od verze 21.2 Angular podporuje čisté JS-funkce v šablonách pro filtrování, hledání a aktualizaci signálů bez metod komponenty. Rozbor příkladů navigace, řazení, předávání funkcí přes input. Omezení: zákaz víceřádkových výrazů a pipeů uvnitř funkcí.

Funkce v šablonách Angular: filtrování a řazení bez tříd
Advertisement 728x90

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

Google AdInline article slot
<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í:

Google AdInline article slot
<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.

Google AdInline article slot

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

Advertisement 728x90

Číst dál