EventEmitter постоянно излучает значение - PullRequest
0 голосов
/ 28 февраля 2020

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

import { Directive, EventEmitter, Input, Output } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { debounceTime, tap } from 'rxjs/operators';
import { Subscription } from 'rxjs';

@Directive({
  selector: '[appAutoSave]',
})
export class AutoSaveDirective {
  @Input() formGroup!: FormGroup;

  private _state!: 'loading' | 'synced' | 'modified' | 'error';

  @Output() stateChange = new EventEmitter<string>();
  @Output() onSubmit = new EventEmitter();
  @Output() formError = new EventEmitter<string>();

  private formSub!: Subscription;

  ngOnInit() {
    this.preloadData();
    this.autoSave();
  }

  preloadData() {
    this.formGroup.markAsPristine();
    // this.state = 'synced';
  }

  // Autosaves form changes
  autoSave() {
    console.log('inside changes');
    this.formSub = this.formGroup.valueChanges
      .pipe(
        tap(change => {
          this.state = 'modified';
        }),
        debounceTime(2000),
        tap(change => {
          if (this.formGroup.valid && this._state === 'modified') {
            // this.onSubmit.emit();
            this.state = 'synced';
          }
        }),
      )
      .subscribe();
  }

  set state(val: any) {
    this._state = val;
    this.stateChange.emit(val);
     if (val === 'synced') {
       this.onSubmit.emit();
     }
  }
  ngOnDestroy() {
    this.formSub.unsubscribe();
  }
}
  changeState(event: string) {
    this.changeHandler.emit(event);
     if (event === 'synced') { // condition
       this.submit(); 
     }
  }

Если я удалю вышеуказанное условие if все работает нормально. Но я должен вызвать функцию submit, когда значения синхронизируются, и пользователь перестал печатать.

    <form
      [formGroup]="situationFormGroup"
      appAutoSave
      (stateChange)="changeState($event)"
    >

Ответы [ 2 ]

0 голосов
/ 28 февраля 2020

В вашем методе автосохранения вы написали tap оператор внутри pipe следующим образом:

tap(change => {
    this.state = 'modified';
})

То, что делает код выше, это для каждого valueChanges в FormGroup будет установлено состояние , которое будет генерировать событие stateChange . Следовательно, для каждого изменения EventEmitter генерирует значения (см. Код в настройщике вашего состояния )

Чтобы избежать этого, сделайте что-то подобное:

tap(change => {
    if(this._state!=='modified'){ 
        this.state = 'modified';
    }
})
0 голосов
/ 28 февраля 2020

Я бы начал с того, что урезал эту директивную ответственность.

Это очень много делает. 'Loading' | синхронизированы | «модифицированный» | 'ошибка'. Я бы предложил создать 3 директивы: (сохранить SOLID)

  • LoadingDirective
  • ErrorDirective
  • TypingDirective

И чем в TypingDirective вы бы отображали этот загрузчик только в начале form.valueChanges, а затем в tap(this.onSubmit.emit(...)) после debounceTime(2000).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...