Skip to content

Commit

Permalink
fix(badge): allow more data types for badge content (#20331)
Browse files Browse the repository at this point in the history
Currently the badge's content is limited to `string` which excludes other legitimate use cases like numbers. These changes turn it into an `string | number | undefined | null` since we aren't actually doing anything with the value, apart from forwarding it.

Fixes #20326.

(cherry picked from commit 75f73ae)
  • Loading branch information
crisbeto authored and wagnermaciel committed Aug 20, 2020
1 parent 8b7cab1 commit c492ba0
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 12 deletions.
31 changes: 25 additions & 6 deletions src/material/badge/badge.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,34 @@ describe('MatBadge', () => {
}));

it('should update the badge based on attribute', () => {
let badgeContentDebugElement = badgeNativeElement.querySelector('.mat-badge-content')!;

expect(badgeContentDebugElement.textContent).toContain('1');
const badgeElement = badgeNativeElement.querySelector('.mat-badge-content')!;
expect(badgeElement.textContent).toContain('1');

testComponent.badgeContent = '22';
fixture.detectChanges();
expect(badgeElement.textContent).toContain('22');
});

it('should be able to pass in falsy values to the badge content', () => {
const badgeElement = badgeNativeElement.querySelector('.mat-badge-content')!;
expect(badgeElement.textContent).toContain('1');

testComponent.badgeContent = 0;
fixture.detectChanges();
expect(badgeElement.textContent).toContain('0');
});

it('should treat null and undefined as empty strings in the badge content', () => {
const badgeElement = badgeNativeElement.querySelector('.mat-badge-content')!;
expect(badgeElement.textContent).toContain('1');

badgeContentDebugElement = badgeNativeElement.querySelector('.mat-badge-content')!;
expect(badgeContentDebugElement.textContent).toContain('22');
testComponent.badgeContent = null;
fixture.detectChanges();
expect(badgeElement.textContent?.trim()).toBe('');

testComponent.badgeContent = undefined;
fixture.detectChanges();
expect(badgeElement.textContent?.trim()).toBe('');
});

it('should apply class based on color attribute', () => {
Expand Down Expand Up @@ -234,7 +253,7 @@ describe('MatBadge', () => {
class BadgeTestApp {
@ViewChild(MatBadge) badgeInstance: MatBadge;
badgeColor: ThemePalette;
badgeContent: string | number = '1';
badgeContent: string | number | undefined | null = '1';
badgeDirection = 'above after';
badgeHidden = false;
badgeSize = 'medium';
Expand Down
19 changes: 14 additions & 5 deletions src/material/badge/badge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ export class MatBadge extends _MatBadgeMixinBase implements OnDestroy, OnChanges
@Input('matBadgePosition') position: MatBadgePosition = 'above after';

/** The content for the badge */
@Input('matBadge') content: string;
@Input('matBadge') content: string | number | undefined | null;

/** Message used to describe the decorated element via aria-describedby */
@Input('matBadgeDescription')
Expand Down Expand Up @@ -188,7 +188,7 @@ export class MatBadge extends _MatBadgeMixinBase implements OnDestroy, OnChanges
if (!this._badgeElement) {
this._badgeElement = this._createBadgeElement();
} else {
this._badgeElement.textContent = this.content;
this._badgeElement.textContent = this._stringifyContent();
}
return this._badgeElement;
}
Expand All @@ -203,7 +203,7 @@ export class MatBadge extends _MatBadgeMixinBase implements OnDestroy, OnChanges
this._clearExistingBadges(contentClass);
badgeElement.setAttribute('id', `mat-badge-content-${this._id}`);
badgeElement.classList.add(contentClass);
badgeElement.textContent = this.content;
badgeElement.textContent = this._stringifyContent();

if (this._animationMode === 'NoopAnimations') {
badgeElement.classList.add('_mat-animation-noopable');
Expand Down Expand Up @@ -246,11 +246,12 @@ export class MatBadge extends _MatBadgeMixinBase implements OnDestroy, OnChanges
/** Adds css theme class given the color to the component host */
private _setColor(colorPalette: ThemePalette) {
if (colorPalette !== this._color) {
const classList = this._elementRef.nativeElement.classList;
if (this._color) {
this._elementRef.nativeElement.classList.remove(`mat-badge-${this._color}`);
classList.remove(`mat-badge-${this._color}`);
}
if (colorPalette) {
this._elementRef.nativeElement.classList.add(`mat-badge-${colorPalette}`);
classList.add(`mat-badge-${colorPalette}`);
}
}
}
Expand All @@ -270,6 +271,14 @@ export class MatBadge extends _MatBadgeMixinBase implements OnDestroy, OnChanges
}
}

/** Gets the string representation of the badge content. */
private _stringifyContent(): string {
// Convert null and undefined to an empty string which is consistent
// with how Angular handles them in inside template interpolations.
const content = this.content;
return content == null ? '' : `${content}`;
}

static ngAcceptInputType_disabled: BooleanInput;
static ngAcceptInputType_hidden: BooleanInput;
static ngAcceptInputType_overlap: BooleanInput;
Expand Down
2 changes: 1 addition & 1 deletion tools/public_api_guard/material/badge.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ export declare class MatBadge extends _MatBadgeMixinBase implements OnDestroy, O
_id: number;
get color(): ThemePalette;
set color(value: ThemePalette);
content: string;
content: string | number | undefined | null;
get description(): string;
set description(newDescription: string);
get hidden(): boolean;
Expand Down

0 comments on commit c492ba0

Please sign in to comment.