BACK
Use casesForm VM — canSubmit/errors/preview одним потоком
Use cases · 17

Form VM — canSubmit/errors/preview одним потоком

Паттерн

Кнопка Submit зависит от value, status, dirty и доступности сервера. Список ошибок — от value и status. Preview — от value. Вместо того чтобы держать четыре async-пайпа в шаблоне, собираем один объект VM, который содержит всё нужное.

Какую проблему решаем

Если связанные данные приходят из разных потоков, шаблон может промежуточно отрендерить несогласованное состояние: например, canSubmit=true, но errors=[required]. Императивные поля в компоненте дают тот же эффект — пять обработчиков, каждый присваивает своё, и порядок выполнения определяет правильность UI.

Операторы и зачем они нужны

  • combineLatest — пересобирает VM при изменении любого источника. Это сердце паттерна.
  • startWith — даёт начальные значения, чтобы combineLatest эмитнул сразу, а не молчал до первого изменения каждого поля.
  • map — чистая projection: из четырёх входов вычисляет {canSubmit, errors, preview}.
  • shareReplay({ bufferSize: 1, refCount: true }) — кеширует последнюю VM. Когда новый подписчик приходит позже — получает текущее состояние сразу.

Подводные камни

  • shareReplay(1) без конфига держит upstream вечно. Используйте object-конфиг с refCount: true.
  • Не вычисляйте canSubmit в нескольких местах (отдельно для кнопки, отдельно для подсказки) — рано или поздно правила разойдутся. Один источник истины — vm.canSubmit.
  • Без startWith combineLatest молчит, пока КАЖДЫЙ источник не эмитнет. Шаблон будет пустой до первого взаимодействия.

Что в итоге получаем

Шаблон получает один согласованный объект, который полностью описывает состояние формы. Никаких промежуточных «полу-валидных» рендеров.

script.ts // TypeScript
CONSOLE · Console Output
Нажмите на запуск, чтобы увидеть результат...