Сигналы в Angular

Главная » Видеоуроки » JavaScript » Сигналы в Angular
В этом видео мы поговорим о сигналах в Angular. Сигналы — это революционное обновление реактивной модели Angular. Они упрощают работу по отслеживанию изменений в компонентах и тем самым оптимизируют работу angular приложения.
Сигнал — это обертка над значением. Создание сигнала довольно простое (см код ниже). Чтобы получить значение сигнала в шаблоне, надо просто вызвать его как функцию.

Какие сигналы есть в Angular:

  • writable signal — сигнал, значение которогог можно изменять (методы set(), update()).
  • computed signal — сигнал, значение которого рассчитывается, когда изменился связанный сигнал. Значение computed сигнала нельзя изменить напрямую.
  • linked signal — это фактически симбиоз первых двух, то значение зависимо от другого, но можно и изменить значение через set(), update()

Также мы рассмотрим методы toSignal и эффекты. toSignal преобразовывает observable в сигнал. Эффекты похожи на computed signal. Но angular не рекомендует их использовать для логики изменения сигналов. Эффекты могут быть полезны в работе с внешней средой (DOM, localStorage и пр).
Сигналы также влияет на имеющиеся сущности в Angular. Мы рассмотрим input сигнал (замена декортаору Input). Сейчас в режиме тестирования находятся сигнальные формы и httpResource.

app.ts

import {
  Component,
  computed,
  inject,
  Injector,
  linkedSignal,
  OnInit,
  Signal,
  signal,
  WritableSignal,
} from '@angular/core';
import { MatToolbar } from '@angular/material/toolbar';
import { UsersService } from './features/users/services/users-service';
import { UserDto } from './core/models/User';
import { AsyncPipe, JsonPipe } from '@angular/common';
import { toSignal } from '@angular/core/rxjs-interop';
import { UserCard } from './user-card/user-card';

@Component({
  selector: 'app-root',
  imports: [MatToolbar, JsonPipe, UserCard],
  templateUrl: './app.html',
  styleUrl: './app.scss',
})
export class App implements OnInit {
  protected title = 'angular-material-app';

  protected myAge: WritableSignal<number> = signal(35);

  protected personalInfo: Signal<string> = computed(() => `My age is ${this.myAge()}`);

  private userService = inject(UsersService);

  shippingOptions = signal<any[]>([
    { id: 0, name: 'Ground' },
    { id: 1, name: 'Air' },
    { id: 2, name: 'Sea' },
  ]);
  selectedOption = linkedSignal<any[], any>({
    // `selectedOption` is set to the `computation` result whenever this `source` changes.
    source: this.shippingOptions,
    computation: (newOptions, previous) => {
      // If the newOptions contain the previously selected option, preserve that selection.
      // Otherwise, default to the first option.
      console.log(newOptions, previous);
      return newOptions.find((opt) => opt.id === previous?.value.id) ?? newOptions[0];
    },
  });
  protected users: Signal<UserDto[]> = signal([]);
  private injector = inject(Injector);

  public ngOnInit() {
    this.users = toSignal(this.userService.getUsers(), {
      initialValue: [],
      injector: this.injector,
    });
  }

  protected changeData() {
    // this.myAge.set(36);
    this.myAge.update((age) => age + 1);

    this.selectedOption.set({ id: 1, name: 'Pidgin' });
  }
}

app.html

<header>
  <mat-toolbar color="primary">
    <span>My App</span>
  </mat-toolbar>
</header>

<p>App title: {{title}}</p>

<p>My age: {{myAge()}}</p>

<p>Personal info {{personalInfo()}}</p>

<p>Selected skill: {{selectedOption().name}}</p>

<!--<p>{{users() | json}}</p>-->


<p>
  <button (click)="changeData()">Change</button>
</p>


<app-user-card [age]="myAge()"></app-user-card>

user-card.ts

import { ChangeDetectionStrategy, Component, input, Input, InputSignal } from '@angular/core';

@Component({
  selector: 'app-user-card',
  imports: [],
  templateUrl: './user-card.html',
  styleUrl: './user-card.scss',
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class UserCard {

  public age: InputSignal<number> = input<number>(0);


}

user-card.html

<p>input age: {{age()}}</p>

0 Comments

Submit a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *


Срок проверки reCAPTCHA истек. Перезагрузите страницу.

Pin It on Pinterest

Share This