diff --git a/components/button/button.component.ts b/components/button/button.component.ts index 9970f59986..49cef36faa 100644 --- a/components/button/button.component.ts +++ b/components/button/button.component.ts @@ -141,10 +141,10 @@ export class NzButtonComponent implements OnDestroy, OnChanges, AfterViewInit, A // The compiler generates the `ɵɵlistener` instruction which wraps the actual listener internally into the // function, which runs `markDirty()` before running the actual listener (the decorated class method). // Since we're preventing the default behavior and stopping event propagation this doesn't require Angular to run the change detection. - fromEvent(this.elementRef.nativeElement, 'click') + fromEvent(this.elementRef.nativeElement, 'click', { capture: true }) .pipe(takeUntil(this.destroy$)) .subscribe(event => { - if (this.disabled && (event.target as HTMLElement)?.tagName === 'A') { + if ((this.disabled && (event.target as HTMLElement)?.tagName === 'A') || this.nzLoading) { event.preventDefault(); event.stopImmediatePropagation(); } diff --git a/components/button/button.spec.ts b/components/button/button.spec.ts index f34b8317b5..d13566d2b9 100644 --- a/components/button/button.spec.ts +++ b/components/button/button.spec.ts @@ -180,6 +180,17 @@ describe('button', () => { // Previously, it would've caused `tick()` to be called 2 times, because 2 click events have been triggered. expect(spy).toHaveBeenCalledTimes(0); }); + + it('prevent default and stop propagation when the button state is loading', fakeAsync(() => { + testBed.component.nzLoading = true; + testBed.fixture.detectChanges(); + const event = new MouseEvent('click'); + const preventDefaultSpy = spyOn(event, 'preventDefault').and.callThrough(); + const stopImmediatePropagationSpy = spyOn(event, 'stopImmediatePropagation').and.callThrough(); + buttonElement.dispatchEvent(event); + expect(preventDefaultSpy).toHaveBeenCalledTimes(1); + expect(stopImmediatePropagationSpy).toHaveBeenCalledTimes(1); + })); }); }); @@ -281,6 +292,13 @@ export class TestButtonIconOnlyComponent {} }) export class TestButtonIconOnlyLoadingComponent {} +@Component({ + template: ` ` +}) +export class TestButtonWithLoadingComponent { + @Input() nzLoading: boolean = false; +} + @Component({ template: `