Обновление:
Если вы действительно хотите, вы можете сделать это с помощью директивы. Попробуйте это:
import { Directive, ElementRef, Input, Renderer2, OnInit } from '@angular/core';
import { Observable, Subject, BehaviorSubject, timer, fromEvent } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Directive({
selector: '[confirm]'
})
export class ConfirmDirective implements OnInit {
@Input('confirm') delete: Function;
private confirm$ = fromEvent(this.el.nativeElement, 'click');
private confirmTimeout: number = 5000;
private timer$: Observable<number>;
private isConfirming = new BehaviorSubject<boolean>(false);
private isConfirming$ = this.isConfirming.asObservable();
constructor(private el: ElementRef, private renderer: Renderer2) {}
ngOnInit() {
this.isConfirming$.subscribe((isConfirming) => this.setLabel(isConfirming));
this.confirm$.subscribe((event: any) => this.doConfirm());
}
setLabel(isConfirming: boolean): void {
// set the correct element text and styles
let text: any;
let textEl = this.renderer.createElement('span');
if (this.el.nativeElement.firstChild) {
this.renderer.removeChild(this.el.nativeElement, this.el.nativeElement.firstChild);
}
if (this.isConfirming.value) { // we are confirming right now
text = this.renderer.createText('Please confirm delete');
this.renderer.addClass(this.el.nativeElement, 'delete');
} else {
text = this.renderer.createText('Delete');
this.renderer.removeClass(this.el.nativeElement, 'delete');
}
this.renderer.appendChild(this.el.nativeElement, text);
}
doConfirm(): void {
if (this.isConfirming.value === false) { // start confirming
this.timer$ = timer(this.confirmTimeout);
this.isConfirming.next(true);
// start the timer
this.timer$
.pipe(
takeUntil(this.confirm$) // stop timer when confirm$ emits (this happens when the button is clicked again)
)
.subscribe(() => {
this.isConfirming.next(false); // timeout done - confirm cancelled
});
} else { // delete confirmation
this.isConfirming.next(false);
this.delete(); // this is the delete action that was passed to the directive
}
}
}
Вы бы применили его к такому элементу, передав в качестве параметра фактический метод delete
.
<button type="button" [confirm]="delete"></button>
Рабочий пример: https://stackblitz.com/edit/angular-wdfcux
Старый ответ:
Не уверен, что директива будет лучшим способом. Возможно, это можно сделать, но вам нужно как-то перехватить обработчик щелчка и / или передать ему метод удаления. Это было бы, вероятно, грязно.
Я бы, вероятно, создал компонент для кнопки удаления и обработал бы его там (ну, на самом деле, это ложь, если бы это был я, я бы использовал собственный диалог confirm
и покончил бы с этим, но вы этого не сделаете хочу).
Примерно так:
import { Component } from '@angular/core';
import { Observable, Subject, timer } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'delete-button',
template: `<button type="button" (click)="delete()" [ngClass]="{ delete: isConfirming }">{{ label }}</button>`,
styles: ['.delete { background-color: teal; color: white; } ']
})
export class DeleteButtonComponent {
private confirmTimeout: number = 5000;
private timer$: Observable<number>;
private cancelTimer = new Subject();
public isConfirming: boolean = false;
constructor() {}
get label(): string {
return this.isConfirming
? 'Please confirm delete'
: 'Delete'
}
delete() {
if (!this.isConfirming) {
this.timer$ = timer(this.confirmTimeout);
this.isConfirming = true;
this.timer$
.pipe(
takeUntil(this.cancelTimer)
).subscribe(() => {
this.isConfirming = false;
}, null, () => this.isConfirming = false);
} else {
this.cancelTimer.next();
// really delete
}
}
}
Рабочий пример: https://stackblitz.com/edit/angular-z6fek4