В версии Angular 17.3 были представлены входы на основе сигналов в качестве реактивной альтернативы декоратору @Input().

Новые входы Angular предоставляют разработчикам новые возможности.

  • Позволяют уже сегодня интегрировать и использовать преимущества сигналов Angular:

более простые способы запуска логики при изменении входных данных;

эффективные решения для получения состояния из входов;

более плавное взаимодействие с OnPush и будущим Zoneless.

  • Обеспечивают повышение качества кода и производительности разработчиков за счет повышения безопасности типов вводимых данных.

Но как применить новый подход на практике? Из этой статьи вы узнаете, как использовать @model — особый тип ввода, который позволяет компонентам обмениваться новыми значениями.

Входы модели

Входы модели в настоящее время находятся в программе Developer Preview.

Представьте, что у вас есть приложение, в котором компонент списка или таблицы отделен от компонента фильтра, и они должны беспрепятственно взаимодействовать. Именно здесь директива @model окажет неоценимую помощь, упрощая и облегчая двунаправленную привязку данных. Рассмотрим практический пример.

Для наглядности создадим приложение, которое отображает список студентов. Этот список можно динамически фильтровать по имени с помощью отдельного компонента фильтра. Полный код примера можно найти на GitHub, а рабочий пример — на StackBlitz.

Начнем с компонента student, где будут отображаться 2 атомарных компонента.

// student.component.html
// Импортируется как "BANANA IN A BOX" (“банан в коробке”)
<app-filter [(filterKeyword)]="keyword" /> 
<app-student-list [filterKeyword]="keyword()" />

// student.component.ts
export class StudentComponent {
  keyword = signal('');
}

В компоненте student объявляем ключевое слово как signal. Оно будет передаваться между компонентами. Если понадобится передать данные в несколько мест, этого можно добиться, переместив const в сервис и беря его оттуда. Теперь перейдем к созданию другого компонента.

Компонент filter для фильтрации студентов по именам

Компонент filter — это простой компонент с объявлением модели и присвоением ей const, чтобы можно было инициировать двунаправленную привязку.

// filter.component.ts
export class FilterComponent {
  filterKeyword = model('');
}

Если вы инициируете модель без начального значения, рассмотрите возможность использования model.required.

Чтобы просто инициировать привязку данных, присваивается const filterKeyword:

<input [(ngModel)]="filterKeyword" />

Это позволит убедиться, что при каждом обновлении filterKeyword будет автоматически подставлять новое значение. Того же результата можно добиться, используя метод filterKeyword.update(() => 'updated value').

Извлечение реактивного значения с помощью computed()

Функция computed() может быть использована для создания вычисляемого Signal, который извлекает реактивное значение из выражения. В нашем случае используем этот метод для обновления списка при каждом изменении фильтра.

  filteredStudents = computed(() =>
STUDENTS.filter((s) =>
s.name.toLocaleLowerCase().includes(this.filterKeyword())
)
);

Заключение

Внедрение в последней предварительной версии Angular входных данных на основе сигналов — это значительный шаг вперед в расширении возможностей двунаправленной привязки данных. Отказавшись от традиционных декораторов @Input() и @Output() и приняв директиву @model, разработчики могут добиться более эффективного и реактивного управления состоянием. Такой подход не только упрощает процесс обработки изменений входа, но и повышает безопасность типов и производительность разработчиков.

Пример компонентов со списком студентов и фильтром демонстрирует, насколько простым и интуитивно понятным может быть двунаправленная привязка данных с помощью новой директивы @model. Используя сигналы, разработчики могут легко управлять изменениями состояния компонентов и распространять их, что приводит к созданию более чистого и удобного кода.

Поскольку Angular продолжает развиваться, использование этих новых реактивных парадигм будет иметь решающее значение для разработчиков, стремящихся создавать надежные и производительные приложения. Директива @model и вычисляемые сигналы предоставляют мощные инструменты для создания отзывчивых и динамичных пользовательских интерфейсов, прокладывая путь к более плавной разработке и более эффективному управлению состоянием.

Чтобы подробнее изучить эту новую функцию, ознакомьтесь с полным кодом примера на GitHub и посмотрите его в действии на  StackBlitz (демо)

Для тех, кому интересно, что означает название “BANANA IN A BOX” (“банан в коробке”):

[] = box (коробка);

() = banana (банан);

[()] = banana in a box (банан в коробке).

Читайте также:

Читайте нас в Telegram, VK и Дзен


Перевод статьи Sunil Soundarapandian: Stop using “@Input” “@output” in Angular

Предыдущая статьяПреобразование кода в UML-диаграммы: раскрытие возможностей PlantUML