NG Stream

Description
Авторский канал об Angular и новостях фронтенда. Мы рассказываем о том, с чем сталкиваемся в процессе разработки, делимся полезными, на наш взгляд, статьями.

Made by devs for 🅰️ devs

Авторы:
- @antoonG
- @basters

Чат: https://t.me/+JYGeE7HekO04Y2My
Advertising
We recommend to visit
HAYZON
HAYZON
5,777,024 @hayzonn

👤 𝐅𝐨𝐮𝐧𝐝𝐞𝐫: @Tg_Syprion
🗓 ᴀᴅᴠᴇʀᴛɪsɪɴɢ: @SEO_Fam
Мои каналы: @mazzafam

Last updated 1 month, 1 week ago

Architec.Ton is a ecosystem on the TON chain with non-custodial wallet, swap, apps catalog and launchpad.

Main app: @architec_ton_bot
Our Chat: @architec_ton
EU Channel: @architecton_eu
Twitter: x.com/architec_ton
Support: @architecton_support

Last updated 1 month ago

Канал для поиска исполнителей для разных задач и организации мини конкурсов

Last updated 1 month, 3 weeks ago

2 months ago

Что с ресурсами?

Попробую в заметке выяснить, что это и коротко подчеркнуть плюсы/минусы, которые вижу я.

Ресурс состоит из функции loader(), возвращающей Promise и опционального сигнала. Функция срабатывает при инициализации ресурса и при изменении параметров сигнала.

cities = resource({ request: () => ({ id: this.id() }), loader: (param) => { return this.service.findCity(param.request); } });

Новое API:
📌 обладает семантикой switchMap. Другими словами, предыдущие запросы будут отклонены и возвращены последние запрашиваемые данные.
📌 позволяет удобно обрабатывать ошибки и состояние загрузки. Можно просто обратиться к ресурсу и получить состояние.

this.cities.isLoading; this.cities.error;

📌 присутствует совместимость с RxJS.

Преимущества
1. Позволяет легко управлять состоянием загрузки, успешного завершения и ошибок без необходимости писать собственные велосипеды.
2. Возможная интеграция с Angular Forms. Это было бы круто связать данные между формами и асинхронными источниками. Есть в сети примеры с linkedSignal и формами.
3. Кэширование данных, что может значительно повысить производительность приложения, уменьшая количество запросов к серверу.

// EditUserComponent userId = input<string>(); userRes = rxResource({ request: () => ({ id: this.userId() }), loader: (param) => this.service.getUser(param.id); }) form = { name: linkedSignal(() => this.userRes.value().name), email: linkedSignal(() => this.userRes.value().email) };

Недостатки
📌 Снова получаем 1000 и 1 способ сделать одно и то же.
Противоречие существующему HttpClient. Очень интересно, представят ли в следующих версиях отдельный HttpClient с тем же API, но возвращающим Promise?
📌 Будет ли такая гибкость, как у RxJS? Пока что есть ощущение, что придется преобразовывать туда/обратно, что приведет к невообразимому количеству бойлерплейта. Если хотели уменьшить порог входа, то получили пока ровно обратное.
Пример, как на фото в комментариях, лично для меня сложно читаем. Это то, что ждут от Angular сейчас? Чтобы не тратить часы на разбор, цель в примере: получить список городов по запрашиваемому году основания.

Чат для обсуждений

#angular

2 months, 1 week ago

Команда Angular (совместно с авторами Angular Space community) обновят весьма устаревший style guide!

На прошлой неделе RFC (Request For Comments) был опубликован, просмотреть у меня получилось только на выходных.

Я предполагал, что в гайде покажут стиль работы с новыми API, интеграции с RxJS, работу с конвертацией toSignal() / toObservable() и тд. Но для этого придется ждать последующих обновлений.

Из интересного:

📌 Автор в комментах предлагает помечать свойства класса, которые используются только в шаблонах, как protected и уже сейчас переписать тесты, опираясь на это правило.
📌 Добавление типа сущности в имена (component, service, pipe) - от данного подхода RFC предлагает отказаться, что вызвало бурное обсуждение. На мой взгляд, подобное правило приведет к путанице. Данный подход не должен быть регламентирован в официальном style guide, а принят в конкретном проекте командой/техлидом и изменен, если считаете, что это лучше отразит функциональность.
📌 Рекомендация писать отдельный файл для шаблона, если размер превышает несколько строк - будет убрана. И здесь, конечно же, отсылка к распространению JSX. О DevExp команда предпочла здесь забыть…

Что же, ждем. После столь значительных нововведений разработчики должны знать, на что ссылаться, применять на проектах. Ссылка на RFC здесь для вас.

Чат для обсуждений

#angular

2 months, 1 week ago
5 months ago

Типизация или опять костылизация?
На прошлой неделе открыл для себя один немаловажный нюанс.

В своем решении мне нужно было передавать в аргумент функции KeyboardEvent. При включенном strict mode и попытке считать значение event.target.value, как в примере ниже, получаем ошибку: TS2339: Property value does not exist on type EventTarget.

```
private keydownHandler(event: KeyboardEvent): void {
if (
event.target &&
event.target.value
) {
...
}
}

```

Первое решение, которое пришло в голову, было сделать принудительный каст. Это решало проблему, но так делать плохо. Гораздо удобнее и правильнее было бы использовать type guard.

```
private keydownHandler(event: KeyboardEvent): void {
if (event.target instanceof HTMLInputElement && event.target.value) {
...
}
}

```

Но, насколько я знаю, HTMLInputElement это интерфейс, соответственно это не сработает. Оказывается, сработает! Дело в том, что если посмотреть в lib.dom.d.ts, то можно найти, что HTMLInputElement это и интерфейс, и объявление класса:

```
interface HTMLInputElement extends HTMLElement, PopoverInvokerElement {...}

declare var HTMLInputElement: {
prototype: HTMLInputElement;
new(): HTMLInputElement;
}
```

Поэтому решение с instanceof сработает. Но похоже, что сделано специально для подобной проверки, но подход весьма сомнительный. А вы знали об этом? И как вы относитесь к подобному решению?

#js

5 months, 2 weeks ago

Web-view, In-app браузеры и недостатки in-app
В чем отличия?

? Web-view — это компонент, интегрированный в приложение, который позволяет отображать веб-страницы. Он использует движки браузеров (WebKit на iOS или Chromium на Android). Навигация может быть ограничена. Например, кнопки вперед/назад могут функционировать по-другому. Кроме того, web-view более уязвим к определенным видам атак, поскольку он может не иметь всех функций безопасности, которые предоставляет полноценный браузер.

? In-app браузер — это обёртка над WebView, которая имеет полный контроль над вашей страницей. Они запускаются из приложения, но работают как полноценные браузеры. Они обычно реализуются через такие компоненты, как Chrome Custom Tabs (на Android) или SFSafariViewController (на iOS). Предоставляют почти все функции полноценного браузера, включая вкладки, расширения и улучшенные функции безопасности. Имеют более высокие меры безопасности, включая защиту от фишинга и автоматические обновления.

На frontend-masters недавно вышла статья, объясняющая, почему такие In-app браузеры зло, и как с ними бороться.

В итоге, выбор между web-view и in-app браузером зависит от целей разработчика и требований к пользовательскому опыту. Web-view может быть удобным для легкой интеграции, но in-app браузеры обеспечивают более привычный функционал и безопасность.

5 months, 2 weeks ago

Миграция на function-based inputs станет удобнее!

В следующей версии Angular появится schematic для миграции decorator-based инпутов на inject function.

Миграция будет выполняться с использованием команды ng generate @angular/core:inject\-migration с несколькими возможными опциями:

- path. Указывается путь миграции. Если оставить пустым, мигрирует всю директорию.
- migrateAbstractClasses. Указывается, если нужно мигрировать абстрактные классы, но есть вероятность, что придется вручную исправлять.
- backwardsCompatibleConstructors. При миграции будет сгенерирована дополнительная сигнатура конструктора для обратной совместимости.

Новый схематик появится в версии 18.2.0 и упростит переход. Ссылка на MR.

#angular

GitHub

Initial logic for signal input migration by devversion · Pull Request #57082 · angular/angular

This commit adds the code for the signal input migration. We've prototyped the migration and made it batchable— so that it can run for larger projects (e.g. using Beam); or in practice all of G...

8 months ago

Отличие Omit и Exclude

При необходимости исключить свойство или набор свойств из типа, мы вспоминаем, что есть Utility types - Omit и Exclude. Но для того чтобы понять, какой применить, зависаешь на несколько секунд. Особенно, если редко с ними работаешь.

Возьмем простейший пример и выкинем ненужные свойства из объекта.

```
interface ITodo {
title: string;
description: string;
completed: boolean;
createdAt: number;
}
type TodoInfo = Omit;

const todoInfo: TodoInfo = {
title: "Title",
description: "Smth description",
};
```

Мы убрали свойства из типа ITodo. Теперь попробуем сделать то же самое с объединением интерфейсов.

interface ITodo { title: string; description: string; completed: boolean; createdAt: number; } interface IWork { id: string; executor: string; } type TodoInfo = Omit<ITodo | IWork, "completed" | "createdAt" | "id">; // type TodoInfo = {}

В этом случае, Omit уже выведет неправильный тип. Переформулируем наши требования. Для такой задачи нужно, чтобы наш условный тип игнорировал ключи, которые содержатся в исходном типе ITodo | IWork. Верно?

Если обратим внимание на определение типов, то увидим, что Exclude делает то, что нужно.

type Exclude<T, U> = T extends U ? never : T;

Он просто проверяет, расширяет ли один тип другой. Если да, то возвращается never, иначе возвращается исходный тип. Exclude, по сути, использует дистрибутивное свойство Conditional types.

Заменим Omit на Exclude в нашем примере. В этом случае TodoInfo все равно выводится криво, но это уже недостатки автовывода типов в TS. В ошибке компилятор выводит требуемые свойства и после их добавления код будет рабочим.

```
// type TodoInfo = ITodo | IWork
type TodoInfo = Exclude;

// Type '{ title: string; description: string; }' is missing the following properties from type 'ITodo': completed, createdAt
const todoInfo: TodoInfo = {
title: "Title",
description: "Smth description",
};
const todoInfo: TodoInfo = {
title: "Title",
description: "Smth description",
completed: false,
createdAt: 1,
};
```

Сделаем вывод.

Omit работает с объектами или интерфейсами, чтобы убрать одну из пар “key-value”

Exclude работает с объединениями (unions), чтобы исключить одно из свойств.

#typescript

We recommend to visit
HAYZON
HAYZON
5,777,024 @hayzonn

👤 𝐅𝐨𝐮𝐧𝐝𝐞𝐫: @Tg_Syprion
🗓 ᴀᴅᴠᴇʀᴛɪsɪɴɢ: @SEO_Fam
Мои каналы: @mazzafam

Last updated 1 month, 1 week ago

Architec.Ton is a ecosystem on the TON chain with non-custodial wallet, swap, apps catalog and launchpad.

Main app: @architec_ton_bot
Our Chat: @architec_ton
EU Channel: @architecton_eu
Twitter: x.com/architec_ton
Support: @architecton_support

Last updated 1 month ago

Канал для поиска исполнителей для разных задач и организации мини конкурсов

Last updated 1 month, 3 weeks ago