diff --git a/src/app/components/badge/badge.ts b/src/app/components/badge/badge.ts index df9cae7a047..583e86179d1 100755 --- a/src/app/components/badge/badge.ts +++ b/src/app/components/badge/badge.ts @@ -1,5 +1,5 @@ import { CommonModule, DOCUMENT } from '@angular/common'; -import { AfterViewInit, ChangeDetectionStrategy, Component, Directive, ElementRef, Inject, Input, NgModule, OnDestroy, Renderer2, ViewEncapsulation, booleanAttribute } from '@angular/core'; +import { AfterViewInit, ChangeDetectionStrategy, Component, Directive, ElementRef, Inject, Input, NgModule, Renderer2, OnChanges, SimpleChanges, ViewEncapsulation, booleanAttribute } from '@angular/core'; import { SharedModule } from 'primeng/api'; import { DomHandler } from 'primeng/dom'; import { UniqueComponentId } from 'primeng/utils'; @@ -13,117 +13,95 @@ import { UniqueComponentId } from 'primeng/utils'; class: 'p-element' } }) -export class BadgeDirective implements AfterViewInit, OnDestroy { - /** - * Icon position of the component. - * @group Props - */ - @Input() iconPos: 'left' | 'right' | 'top' | 'bottom' = 'left'; +export class BadgeDirective implements OnChanges, AfterViewInit { /** * When specified, disables the component. * @group Props */ - @Input('badgeDisabled') get disabled(): boolean { - return this._disabled; - } - set disabled(val: boolean) { - this._disabled = val; - } + @Input('badgeDisabled') public disabled: boolean; /** * Size of the badge, valid options are "large" and "xlarge". * @group Props */ - @Input() public get size(): 'large' | 'xlarge' { - return this._size; - } - set size(val: 'large' | 'xlarge') { - this._size = val; - - if (this.initialized) { - this.setSizeClasses(); - } - } + @Input() public badgeSize: 'large' | 'xlarge'; /** - * Value to display inside the badge. + * Severity type of the badge. * @group Props */ - @Input() get value(): string { - return this._value; - } - set value(val: string) { - if (val !== this._value) { - this._value = val; - - if (this.initialized) { - let badge: HTMLElement = document.getElementById(this.id) as HTMLElement; - - if (this._value) { - if (DomHandler.hasClass(badge, 'p-badge-dot')) DomHandler.removeClass(badge, 'p-badge-dot'); - - if (String(this._value).length === 1) { - DomHandler.addClass(badge, 'p-badge-no-gutter'); - } else { - DomHandler.removeClass(badge, 'p-badge-no-gutter'); - } - } else if (!this._value && !DomHandler.hasClass(badge, 'p-badge-dot')) { - DomHandler.addClass(badge, 'p-badge-dot'); - } - - badge.innerHTML = ''; - this.renderer.appendChild(badge, document.createTextNode(this._value)); - } - } - } + @Input() public severity: 'success' | 'info' | 'warning' | 'danger' | null | undefined; /** - * Severity type of the badge. + * Value to display inside the badge. * @group Props */ - @Input() severity: 'success' | 'info' | 'warning' | 'danger' | null | undefined; - - public _value!: string; - - public initialized: boolean = false; + @Input() public value: string | number; private id!: string; - private _disabled: boolean = false; + private get activeElement(): HTMLElement { + return this.el.nativeElement.nodeName.indexOf('-') != -1 ? this.el.nativeElement.firstChild : this.el.nativeElement; + } - private _size!: 'large' | 'xlarge'; + private get canUpdateBadge(): boolean { + return this.id && !this.disabled; + } constructor(@Inject(DOCUMENT) private document: Document, public el: ElementRef, private renderer: Renderer2) {} - ngAfterViewInit() { - this.id = UniqueComponentId() + '_badge'; - let el = this.el.nativeElement.nodeName.indexOf('-') != -1 ? this.el.nativeElement.firstChild : this.el.nativeElement; + public ngOnChanges({ value, size, severity, disabled }: SimpleChanges): void { + if (disabled) { + this.toggleDisableState(); + } - if (this._disabled) { - return null; + if (!this.canUpdateBadge) { + return; } - let badge = this.document.createElement('span'); - badge.id = this.id; - badge.className = 'p-badge p-component'; + if (severity) { + this.setSeverity(severity.previousValue); + } - if (this.severity) { - DomHandler.addClass(badge, 'p-badge-' + this.severity); + if (size) { + this.setSizeClasses(); } - this.setSizeClasses(badge); + if (value) { + this.setValue(); + } + } + + public ngAfterViewInit(): void { + this.id = UniqueComponentId() + '_badge'; + this.renderBadgeContent(); + } + + private setValue(element?: HTMLElement): void { + const badge = element ?? this.document.getElementById(this.id); + + if (!badge) { + return; + } if (this.value != null) { - this.renderer.appendChild(badge, this.document.createTextNode(this.value)); + if (DomHandler.hasClass(badge, 'p-badge-dot')) { + DomHandler.removeClass(badge, 'p-badge-dot'); + } - if (String(this.value).length === 1) { + if (this.value && String(this.value).length === 1) { DomHandler.addClass(badge, 'p-badge-no-gutter'); + } else { + DomHandler.removeClass(badge, 'p-badge-no-gutter'); } } else { - DomHandler.addClass(badge, 'p-badge-dot'); - } + if (!DomHandler.hasClass(badge, 'p-badge-dot')) { + DomHandler.addClass(badge, 'p-badge-dot'); + } - DomHandler.addClass(el, 'p-overlay-badge'); - this.renderer.appendChild(el, badge); + DomHandler.removeClass(badge, 'p-badge-no-gutter'); + } - this.initialized = true; + badge.innerHTML = ''; + const badgeValue = this.value != null ? String(this.value) : ''; + this.renderer.appendChild(badge, this.document.createTextNode(badgeValue)); } private setSizeClasses(element?: HTMLElement): void { @@ -133,13 +111,13 @@ export class BadgeDirective implements AfterViewInit, OnDestroy { return; } - if (this._size) { - if (this._size === 'large') { + if (this.badgeSize) { + if (this.badgeSize === 'large') { DomHandler.addClass(badge, 'p-badge-lg'); DomHandler.removeClass(badge, 'p-badge-xl'); } - if (this._size === 'xlarge') { + if (this.badgeSize === 'xlarge') { DomHandler.addClass(badge, 'p-badge-xl'); DomHandler.removeClass(badge, 'p-badge-lg'); } @@ -149,8 +127,53 @@ export class BadgeDirective implements AfterViewInit, OnDestroy { } } - ngOnDestroy() { - this.initialized = false; + private renderBadgeContent(): void { + if (this.disabled) { + return null; + } + + const el = this.activeElement; + const badge = this.document.createElement('span'); + badge.id = this.id; + badge.className = 'p-badge p-component'; + + this.setSeverity(null, badge); + this.setSizeClasses(badge); + this.setValue(badge); + DomHandler.addClass(el, 'p-overlay-badge'); + this.renderer.appendChild(el, badge); + } + + private setSeverity(oldSeverity?: 'success' | 'info' | 'warning' | 'danger' | null, element?: HTMLElement): void { + const badge = element ?? this.document.getElementById(this.id); + + if (!badge) { + return; + } + + if (this.severity) { + DomHandler.addClass(badge, `p-badge-${this.severity}`); + } + + if (oldSeverity) { + DomHandler.removeClass(badge, `p-badge-${oldSeverity}`); + } + } + + private toggleDisableState(): void { + if (!this.id) { + return; + } + + if (this.disabled) { + const badge = this.activeElement?.querySelector(`#${this.id}`); + + if (badge) { + this.renderer.removeChild(this.activeElement, badge); + } + } else { + this.renderBadgeContent(); + } } } /** @@ -182,7 +205,7 @@ export class Badge { * Size of the badge, valid options are "large" and "xlarge". * @group Props */ - @Input() size: 'large' | 'xlarge' | undefined; + @Input() badgeSize: 'large' | 'xlarge' | undefined; /** * Severity type of the badge. * @group Props @@ -192,7 +215,7 @@ export class Badge { * Value to display inside the badge. * @group Props */ - @Input() value: string | null | undefined; + @Input() value: string | number | null | undefined; /** * When specified, disables the component. * @group Props @@ -203,8 +226,8 @@ export class Badge { return { 'p-badge p-component': true, 'p-badge-no-gutter': this.value != undefined && String(this.value).length === 1, - 'p-badge-lg': this.size === 'large', - 'p-badge-xl': this.size === 'xlarge', + 'p-badge-lg': this.badgeSize === 'large', + 'p-badge-xl': this.badgeSize === 'xlarge', 'p-badge-info': this.severity === 'info', 'p-badge-success': this.severity === 'success', 'p-badge-warning': this.severity === 'warning', diff --git a/src/app/showcase/doc/apidoc/index.json b/src/app/showcase/doc/apidoc/index.json index a2ccdbba80f..755a5317b33 100644 --- a/src/app/showcase/doc/apidoc/index.json +++ b/src/app/showcase/doc/apidoc/index.json @@ -4455,41 +4455,34 @@ "props": { "description": "Defines the input properties of the component.", "values": [ - { - "name": "iconPos", - "optional": false, - "readonly": false, - "type": "\"left\" | \"top\" | \"bottom\" | \"right\"", - "default": "left", - "description": "Icon position of the component." - }, { "name": "disabled", "optional": false, "readonly": false, "type": "boolean", + "default": "false", "description": "When specified, disables the component." }, { - "name": "size", + "name": "badgeSize", "optional": false, "readonly": false, "type": "\"large\" | \"xlarge\"", "description": "Size of the badge, valid options are \"large\" and \"xlarge\"." }, { - "name": "value", + "name": "severity", "optional": false, "readonly": false, - "type": "string", - "description": "Value to display inside the badge." + "type": "\"success\" | \"info\" | \"warning\" | \"danger\"", + "description": "Severity type of the badge." }, { - "name": "severity", + "name": "value", "optional": false, "readonly": false, - "type": "\"success\" | \"info\" | \"warning\" | \"danger\"", - "description": "Severity type of the badge." + "type": "string | number", + "description": "Value to display inside the badge." } ] } @@ -4514,7 +4507,7 @@ "description": "Inline style of the element." }, { - "name": "size", + "name": "badgeSize", "optional": false, "readonly": false, "type": "\"large\" | \"xlarge\"", @@ -4531,7 +4524,7 @@ "name": "value", "optional": false, "readonly": false, - "type": "string", + "type": "string | number", "description": "Value to display inside the badge." }, { diff --git a/src/app/showcase/doc/badge/sizedoc.ts b/src/app/showcase/doc/badge/sizedoc.ts index d9f8a5bb498..905445f1a0d 100644 --- a/src/app/showcase/doc/badge/sizedoc.ts +++ b/src/app/showcase/doc/badge/sizedoc.ts @@ -5,24 +5,24 @@ import { Code } from '../../domain/code'; selector: 'badge-size-demo', template: ` -

Badge sizes are adjusted with the size property that accepts large and xlarge as the possible alternatives to the default size. Currently sizes only apply to component mode.

+

Badge sizes are adjusted with the badgeSize property that accepts large and xlarge as the possible alternatives to the default size. Currently sizes only apply to component mode.

- - + +
` }) export class SizeDoc { code: Code = { - basic: ``, + basic: ``, html: `
- - + +
`, typescript: ` import { Component } from '@angular/core';