Угловая директива, которая ожидает нажатия кнопки Обещание для завершения - PullRequest
0 голосов
/ 14 февраля 2019

Обновление 1: Основываясь на ответе @PierreDuc, я разработал и создал здесь более простую версию: Упрощенный пример .Чувак, я помню, как в AngularJS была возможность полностью взломать (щелкнуть) функцию и выполнить ее.Я понимаю, я понимаю, мне нравится упрощенное предложение ниже, хотя.Это должно работать для меня:)

Я создал директиву Angular для кнопки, которая принимает метод в качестве Promise.
При нажатии я отключаю кнопку.Когда Обещание выполнено, я снова активирую кнопку.

По сути, при нажатии я хочу отключить кнопку, пока не будет завершена вся обработка, выполняемая этим событием кнопки, включая любые вызовы http.

Я выполнил свою цель, показанную здесь: Пример Stackblitz .

Мне не особенно нравится мое "решение".

Это слишком сложно.Чтобы заставить его работать, должно произойти три вещи.

  1. Директива добавляется к кнопке.
  2. Устанавливается свойство "waitFor".
  3. Функция "waitFor" должна быть функцией, которая возвращает Promise.

ИМО, это слишком много вещей, которые нужно выровнять, чтобы заставить его работать.

Что я действительно хотел бы сделать, так это получить представление о методе (click)Нажмите кнопку и выполните ее вручную в директиве так же, как я сделал свое свойство waitFor.

Как я могу это сделать?

Как минимум, я бы хотел директиву, которая нетребуется как имя директивы ("appClickWait"), так и свойство ("[waitFor]").

Вот код для вашего удобства:

Директива:

import { Directive, HostListener, ElementRef, Output, Input, EventEmitter, Renderer2 } from '@angular/core';

// Enfore this directvie can only be used on a button?
@Directive({
  selector: '[appClickWait]'
})
export class ClickWaitDirective {
  @Input("waitFor") clickWait: any;

  constructor(private el: ElementRef, private renderer: Renderer2) { }

  @HostListener('click', ['$event'])
  clickEvent(event) {
    event.preventDefault();
    event.stopPropagation();

    this.renderer.setAttribute(this.el.nativeElement, 'disabled', 'disabled');

    const originalInnerText = this.el.nativeElement.innerText;

    this.el.nativeElement.innerText = 'Processing...';

    const reset = () => {
      this.renderer.removeAttribute(this.el.nativeElement, 'disabled');

      this.el.nativeElement.innerText = originalInnerText;
    };

    // I really would like to just get a handle on the (click) function here
    // that would greatly simplify the useage of this directive
    this.clickWait()
      .then((data) => {
        reset();
      })
      .catch(err => {
        console.error(err);

        reset();
      });
  }
}

Шаблон:

  myClickFunc = async () => {
    console.log('start')

    this.posts = [];

    // too fast, let's wait a bit
    // this.posts = await this.http.get('https://jsonplaceholder.typicode.com/posts').toPromise();

    await new Promise((resolve, reject) => {
      setTimeout(async () => {
        try {
          this.posts = await this.http.get('https://jsonplaceholder.typicode.com/posts').toPromise();
        } catch (err) {
          reject(err);
        }
        resolve();
      }, 1000);
    });

    console.log('all done');
  }
<button type="button" appClickWait [waitFor]="myClickFunc">Single Wait Click</button>

Спасибо!

1 Ответ

0 голосов
/ 14 февраля 2019

Полагаю, вы можете упростить это до:

@Directive({
  selector: 'button[appClickWait]'
})
export class ClickWaitDirective {
  @HostBinding('disabled')
  public waiting = false;

  @Input()
  appClickWait: () => Observable<any> | Promise<any> = async() => void 0;

  @HostListener('click')
  clickEvent() {
    this.waiting = true;

    from(this.appClickWait()).pipe(take(1)).subscribe({
      subscribe: () => this.waiting = false,
      complete: () => this.waiting = false,
      error: (e) => {
        console.error(e);
        this.waiting = false;
      }
    })
  }
}

При таком использовании:

<button [appClickWait]="myClickFunc">Single Wait Click</button>

myClickFunc = () => this.callHttp();

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

stack ;

...