Сигналы в 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