Подписка на Observable на основе условий - PullRequest
1 голос
/ 30 сентября 2019

Фон

Я использую Reactive Forms, который расширяется на две вкладки (первая половина одной страницы имеет вкладки), а затем длинная страница с кнопкой Submit внизу. Я выполняю проверку по нажатию кнопки «Отправить».

При нажатии кнопки «Отправить» страница должна перейти к полю формы ошибки при сбое проверки.

Я также могу загрузитьвкладка основана на ошибках в FormGroups.

Задача

  1. Прокрутка происходит до загрузки вкладки.
  2. Чтобы решить пункт 1, яподписался на событие animationDone, а затем прокрутил его до точки внутри него.
submit(){
   //code to select the desired tab
   this.selectedTab.animationDone.subscribe(res => {
   this.myElement.nativeElement.ownerDocument.getElementsByClassName('ng-invalid mat-form-field')[0].scrollIntoView({ behavior: 'smooth' });
          });
}

До этого момента все работает нормально !!!

После нажатия кнопки «Подтвердить» подписка подписывается, и страница прокручивается до ошибок при выборе новой вкладки. Я хотел отменить подписку на эту заметку, а затем подписываться на нее каждый раз, когда нажимается кнопка «Отправить».

Я пытался отписаться, но я не могу снова подписаться на нее. Это иногда разрушает функцию подписки и выдает ошибку

Я думаю, что что-то упустил и обратился за помощью. Спасибо заранее !!

Дополнительный код по запросу

submit()
{
    if(this.bookingForm.valid){
    // do some actions ....
     }
    else {
    this.bookingForm.markAllAsTouched();
    //subscribing to the event before selecting the tab

    this.selectedTab.animationDone.subscribe(res => {

     this.myElement.nativeElement.ownerDocument.getElementsByClassName('ng-invalid mat-form-field')[0].scrollIntoView({ behavior: 'smooth' });

          });

    // code to select the Tab where the error occurs .....
     this.selectedTab.selectedIndex = this.errorIndex;

    //unsubscribe
    this.selectedTab.animationDone.unsubscribe()

    } // close of else block
}// close of submit Function

Отмена подписки (или аналогичная функция) необходима, так как она должна подписываться только при нажатии кнопки «Отправить»,Если она не отписана (или приостановлена), то функция подписки вызывается при каждом изменении вкладки, и страница продолжает прокручиваться вверх и вниз в зависимости от ошибок.

Просмотр страницы

Это только для демонстрации. Page view

РЕДАКТИРОВАТЬ 2 ниже

Вот ссылка StackBlitz . Это всего лишь примерная страница, моя страница имеет гораздо больше полей и групп по сравнению с этой.

Воссоздание проблемы

Сценарий 1

  1. Заполните поля - Имя, Tab1, Details1
  2. Оставьте tab1 выбранным и нажмите Submit.
  3. Это должно прокрутить вверх и показать Tab2 . Работает как положено! Задержка является приемлемой.
  4. Теперь вручную переключитесь на Tab1.
  5. Вы можете увидеть прокрутку страницы в поле Details 2.
  6. Эта прокрутка происходит всякий раз, когда вкладка Как мне это остановить?
  7. Я могу добиться этого, раскомментировав строку 38 в файле app.component.ts. - Команда отписаться.
    • В этом случае возникает ошибка, когда я нажимаю кнопку «Отправить» более одного раза.
    • Когда я нажимаю второй раз, подписка не работает.

1 Ответ

1 голос
/ 03 октября 2019

Извините за поздний ответ. Я был немного занят.

Я не изучал ту часть animation, которую вы пробовали, вместо этого я сосредоточился на основах, поскольку нам просто нужно было сосредоточиться на элементе, если он равен invalid.

Метод 1

submit() {
  if(this.testForm.valid) {
    //Code to Submit
  } else {
    ((document.getElementsByClassName('mat-input-element ng-invalid')[0]) as HTMLElement).focus();
  }
}

Метод 2

Я наткнулся на этот очень крутой способ сделать это.

import { MatInput } from '@angular/material';
import { QueryList, ViewChildren } from '@angular/core';

@ViewChildren(MatInput) inputs: QueryList <MatInput>;

submit() {
  if(this.testForm.valid) {
    //Code to Submit
  } else {
    this.inputs.find(input => !input.ngControl.valid).focus();
  }
}

Кроме того, если вы всегда хотите, чтобы сначала был выбран Tab 1, если это invalid, затем поставьтедругое условие в секции else/ else if -

if(this.testForm.get('tab1').errors) {
  this.tabControl.selectedIndex = 0;
} else if(this.testForm.get('tab2').errors) {
  this.tabControl.selectedIndex = 1;
}

Еще одна вещь, вам нужно будет сделать небольшую задержку, прежде чем сосредоточиться на элементах invalid, так как создается элемент input для Tab 2 в DOM занимает наносекунды времени и фокусируется на Details 1, если Tab 1 или 2 равен invalid.

delay(ms: number) {
    return new Promise( resolve => setTimeout(resolve, ms) );
  }

Просто позвоните до focus() и после switching tabs check

await this.delay(1);

Если вы не хотите устанавливать delay, просто установите focus() на animationDone событие еще раз и установите минимальное время animationDuration, чтобы вы не видели focus на Details 1 в режиме реального времени.

ФоПроследите за ссылками Methods для полного прохождения и дайте мне знать, если у вас возникнут какие-либо проблемы.

...