Use cases/Form 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 молчит, пока КАЖДЫЙ источник не эмитнет. Шаблон будет пустой до первого взаимодействия.
Что в итоге получаем
Шаблон получает один согласованный объект, который полностью описывает состояние формы. Никаких промежуточных «полу-валидных» рендеров.