Отключить в директиве не сбрасывать - PullRequest
0 голосов
/ 16 октября 2019

После этого Stackblitz

У меня есть директива, согласно которой при нажатии кнопка должна отключаться до определенного времени (для предотвращения двойного щелчка).

<button appThrottleClick (throttleClick)="click()">
  BUTTON
</button>

<button appThrottleClick [disabled]="myValue" (throttleClick)="click()">
  BUTTON VALUE
</button> 

Я бы хотел, чтобы кнопка была отключена, а затем снова активирована через x секунд. Используя эту директиву здесь:

@Directive({
    selector: '[appThrottleClick]'
})
export class ThrottleClickDirective implements OnInit, OnDestroy {
    @HostBinding('attr.disabled') disabled: boolean;

    @Input() throttleTime = 200;

    @Output() throttleClick = new EventEmitter();

    private clicks = new Subject();
    private subscription: Subscription;

    constructor() { }

    ngOnInit() {
        this.subscription = this.clicks.pipe(
            throttleTime(this.throttleTime)
        ).subscribe(e => {
            this.throttleClick.emit(e);
        });
    }

    ngOnDestroy() {
        this.subscription.unsubscribe();
    }

    @HostListener('click', ['$event'])
    clickEvent(event) {
        console.log('click')
        if (this.disabled) { return; }
        event.preventDefault();
        event.stopPropagation();
        this.disabled = true;
        this.clicks.next(event);
        setTimeout(() => { this.disabled = false; console.log('reset')}, this.throttleTime);
    }
}

В основном:

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

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

Ответы [ 2 ]

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

Вместо использования @HostBinding us ElementRef для отключения и включения кнопки, чтобы ваша директива была

import { Directive, EventEmitter, HostListener, Input, OnDestroy, OnInit, Output, HostBinding,ElementRef } from '@angular/core';
import { throttleTime } from 'rxjs/operators';
import { Subject, Subscription } from 'rxjs';

@Directive({
    selector: '[appThrottleClick]'
})
export class ThrottleClickDirective implements OnInit, OnDestroy {
    @Input() throttleTime = 1000;

    @Output() throttleClick = new EventEmitter();

    private clicks = new Subject();
    private subscription: Subscription;

    constructor(private _elementRef:ElementRef) { }

    ngOnInit() {
        this.subscription = this.clicks.pipe(
            throttleTime(this.throttleTime)
        ).subscribe(e => {
            this.throttleClick.emit(e);
        });
    }

    ngOnDestroy() {
        this.subscription.unsubscribe();
    }

    @HostListener('click', ['$event'])
    clickEvent(event) {
        console.log('click')
        event.preventDefault();
        event.stopPropagation();
        this._elementRef.nativeElement.disabled=true; 
        this.clicks.next(event);
        setTimeout(() => {
          console.log('reset')
           this._elementRef.nativeElement.disabled=false; 
           }, this.throttleTime);
    }
}

demo

0 голосов
/ 16 октября 2019

Вам нужно использовать disabled вместо attr.disabled при использовании HostBinding в вашем ThrottleClickDirective, образце стекаблиц :

...
export class ThrottleClickDirective implements OnInit, OnDestroy {
    @HostBinding('disabled') disabled: boolean;

    @Input() throttleTime = 200;
...

РЕДАКТИРОВАТЬ: Вы можете использовать ссылку на элемент в качестве обходного пути, чтобы проверить свойство nodeName для правильного использования директивы, если директиву необходимо использовать и с другими элементами:

...
    constructor(private element: ElementRef) { }
...
        this.clicks.next(event);
        setTimeout(() => {
          if (this.element.nativeElement.nodeName == "DIV")
            this.disabled = false;
          else if (this.element.nativeElement.nodeName == "BUTTON")
            this.element.nativeElement.removeAttribute('disabled');
          console.log('reset')
        },
        this.throttleTime);
...
...