From dfa8e46a5f4fcaeca585d74779f38c5f29e8b08b Mon Sep 17 00:00:00 2001 From: Egor Volvachev Date: Mon, 9 Jan 2023 12:39:09 +0300 Subject: [PATCH] fix(primeng/p-button): incorrect work with dynamic classes, fixed duplication classes Fixes #12456. --- src/app/components/button/button.ts | 53 +++++++++++++++++++---------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/src/app/components/button/button.ts b/src/app/components/button/button.ts index 7ed42841da4..741ea030561 100755 --- a/src/app/components/button/button.ts +++ b/src/app/components/button/button.ts @@ -7,6 +7,15 @@ import { ObjectUtils } from 'primeng/utils'; type ButtonIconPosition = 'left' | 'right' | 'top' | 'bottom'; +const INTERNAL_BUTTON_CLASSES = { + button: 'p-button', + component: 'p-component', + iconOnly: 'p-button-icon-only', + disabled: 'p-disabled', + loading: 'p-button-loading', + labelOnly: 'p-button-loading-label-only' +} as const; + @Directive({ selector: '[pButton]', host: { @@ -66,13 +75,16 @@ export class ButtonDirective implements AfterViewInit, OnDestroy { public initialized: boolean; - public _initialStyleClass: string; + private get htmlElement(): HTMLElement { + return this.el.nativeElement as HTMLElement; + } + + private _internalClasses: string[] = Object.values(INTERNAL_BUTTON_CLASSES); constructor(public el: ElementRef) {} ngAfterViewInit() { - this._initialStyleClass = this.el.nativeElement.className; - DomHandler.addMultipleClasses(this.el.nativeElement, this.getStyleClass()); + DomHandler.addMultipleClasses(this.htmlElement, this.getStyleClass().join(' ')); this.createIcon(); this.createLabel(); @@ -80,24 +92,28 @@ export class ButtonDirective implements AfterViewInit, OnDestroy { this.initialized = true; } - getStyleClass(): string { - let styleClass = 'p-button p-component'; - if (this.icon && !this.label && ObjectUtils.isEmpty(this.el.nativeElement.textContent)) { - styleClass = styleClass + ' p-button-icon-only'; + getStyleClass(): string[] { + const styleClass: string[] = [INTERNAL_BUTTON_CLASSES.button, INTERNAL_BUTTON_CLASSES.component]; + + if (this.icon && !this.label && ObjectUtils.isEmpty(this.htmlElement.textContent)) { + styleClass.push(INTERNAL_BUTTON_CLASSES.iconOnly); } if (this.loading) { - styleClass = styleClass + ' p-disabled p-button-loading'; - if (!this.icon && this.label) styleClass = styleClass + ' p-button-loading-label-only'; + styleClass.push(INTERNAL_BUTTON_CLASSES.disabled, INTERNAL_BUTTON_CLASSES.loading); + + if (!this.icon && this.label) { + styleClass.push(INTERNAL_BUTTON_CLASSES.labelOnly); + } } return styleClass; } setStyleClass() { - let styleClass = this.getStyleClass(); - this._initialStyleClass = this.el.nativeElement.className; - this.el.nativeElement.className = styleClass + ' ' + this._initialStyleClass; + const styleClass = this.getStyleClass(); + this.htmlElement.classList.remove(...this._internalClasses); + this.htmlElement.classList.add(...styleClass); } createLabel() { @@ -106,10 +122,11 @@ export class ButtonDirective implements AfterViewInit, OnDestroy { if (this.icon && !this.label) { labelElement.setAttribute('aria-hidden', 'true'); } + labelElement.className = 'p-button-label'; labelElement.appendChild(document.createTextNode(this.label)); - this.el.nativeElement.appendChild(labelElement); + this.htmlElement.appendChild(labelElement); } } @@ -130,15 +147,15 @@ export class ButtonDirective implements AfterViewInit, OnDestroy { DomHandler.addMultipleClasses(iconElement, iconClass); } - this.el.nativeElement.insertBefore(iconElement, this.el.nativeElement.firstChild); + this.htmlElement.insertBefore(iconElement, this.htmlElement.firstChild); } } updateLabel() { - let labelElement = DomHandler.findSingle(this.el.nativeElement, '.p-button-label'); + let labelElement = DomHandler.findSingle(this.htmlElement, '.p-button-label'); if (!this.label) { - labelElement && this.el.nativeElement.removeChild(labelElement); + labelElement && this.htmlElement.removeChild(labelElement); return; } @@ -146,10 +163,10 @@ export class ButtonDirective implements AfterViewInit, OnDestroy { } updateIcon() { - let iconElement = DomHandler.findSingle(this.el.nativeElement, '.p-button-icon'); + let iconElement = DomHandler.findSingle(this.htmlElement, '.p-button-icon'); if (!this.icon && !this.loading) { - iconElement && this.el.nativeElement.removeChild(iconElement); + iconElement && this.htmlElement.removeChild(iconElement); return; }