Сценарий

У нас есть кнопка «Далее» в шаговом компоненте. Кнопка должна быть отключена до тех пор, пока форма не будет действительна.

Подход

В AppStateServiceсоздайте два свойства Observable:

  • onFormChanged$:Observable<boolean>
  • isFormValid:Observable<boolean>

onFormChange$

Этот наблюдаемый уведомляет об изменениях формы.

isFormValid$

Это Observable уведомляет нас о том, действительна ли форма.

Реализация Slice OStore Observable

const ON_FORM_CHANGE = 'ON_FORM_CHANGE'
const IS_FORM_VALID = 'IS_FORM_VALID'
constructor() {
    this.ostore.post(ON_FORM_CHANGE, false)
    this.ostore.post(IS_FORM_VALID, false)
this.onFormChanged$:Observable<boolean> =
        this.ostore.
        observe(ON_FORM_CHANGE)
this.isFormValid$:Observable<boolean> =
        this.ostore.
        observe(IS_FORM_VALID)
}

Метод уведомления об изменении формы утилиты

Создайте служебный метод, который запускает уведомления об изменении формы:

emitFormChanged() {
    this.ostore.
    put(ON_FORM_CHANGE, true)
}

Звоните onFormChanged() всякий раз, когда форма изменяется:

this.form.valueChanges.pipe(untilDestroyed(this)).
subscribe(()=>{
    this.state.onFormChanged()
})

Реагировать на изменения формы

Внутри AppStateService создайте служебный метод, который переключает isFormValid$:

toggleIsFormValid(valid:boolean) {
    this.ostore.put(IS_FORM_VALID, valid)
}

Внутри ActionService создайте действие, которое заставит isFormValid$ уведомлять:

enableParameterFormNextButton() {
    this.state.emitFormChanged$.
    pipe(untilDestroyed(this)).subscribe(()=>{
        this.state.toggleIsFormValid(
        this.formService.form.valid)
    })
}

И, наконец, включите или отключите кнопку при срабатывании isFormValid$:

<button matStepperNext [disabled]="!(state.isFormValid$ | async)"
mat-button>Next</button>

Резюме

Теперь у нас есть возможность обновить любую точку в приложении о том, является ли форма действительной или измененной.

Эти события могут запускаться вне контекста приложения. Весь код, который мы реализовали, находится в AppStateService и ActionService, и поэтому модуль, тестирующий триггеры событий и соответствующие действия, становится простым. Мы могли бы создавать все наши события вне какой-либо среды приложения (React, Angular, Vue и т. д.) и просто вставлять события в триггеры событий пользовательского интерфейса.