等待单击Promise完成的Angular指令

问题描述 投票:1回答:1

更新1:根据@PierreDuc的回答,我在这里分叉并创建了一个更简单的版本:Simplified Example。伙计,我记得AngularJS能够完全劫持(点击)功能并执行它。我明白了,我明白了,我喜欢下面的简化提案。这应该对我有用:)

我创建了一个Angular按钮指令,它接受一个方法作为Promise。 点击,我禁用按钮。当Promise解决后,我重新启用按钮。

基本上,点击我想要禁用该按钮,直到完成所有处理该按钮事件,包括任何http调用。

我完成了我在这里看到的目标:Stackblitz Example

我不是特别喜欢我的“解决方案”。

这太复杂了。为了使它工作,需要做三件事。

  1. 该指令将添加到按钮中。
  2. 设置“waitFor”属性。
  3. “waitFor”函数必须是一个返回Promise的函数。

国际海事组织,这是太多需要调整以使其发挥作用的事情。

我真正想做的是获取按钮的(单击)方法,并在指令中手动执行它,就像我执行“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>

谢谢!

angular es6-promise angular-directive
1个回答
2
投票

我想你可以简化它:

@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属性将自动设置,您可以插入一个返回promise或observable的函数。

stack;

© www.soinside.com 2019 - 2024. All rights reserved.