mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
fix(badge): duplicate leftover badge after server-side render (#15417)
Fixes badges being left over if the current page was rendered via Angular Universal. This can cause issues, because the ids on the badges can clash.
This commit is contained in:
committed by
Joey Perrott
parent
ddeeb18b0b
commit
c5a32c214e
@@ -11,10 +11,12 @@ describe('MatBadge', () => {
|
||||
let badgeDebugElement: DebugElement;
|
||||
|
||||
beforeEach(fakeAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [MatBadgeModule],
|
||||
declarations: [BadgeTestApp],
|
||||
}).compileComponents();
|
||||
TestBed
|
||||
.configureTestingModule({
|
||||
imports: [MatBadgeModule],
|
||||
declarations: [BadgeTestApp, PreExistingBadge, NestedBadge],
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(BadgeTestApp);
|
||||
testComponent = fixture.debugElement.componentInstance;
|
||||
@@ -184,6 +186,20 @@ describe('MatBadge', () => {
|
||||
expect(badgeContent.hasAttribute('aria-label')).toBe(false);
|
||||
});
|
||||
|
||||
it('should clear any pre-existing badges', () => {
|
||||
const preExistingFixture = TestBed.createComponent(PreExistingBadge);
|
||||
preExistingFixture.detectChanges();
|
||||
|
||||
expect(preExistingFixture.nativeElement.querySelectorAll('.mat-badge-content').length).toBe(1);
|
||||
});
|
||||
|
||||
it('should not clear badge content from child elements', () => {
|
||||
const preExistingFixture = TestBed.createComponent(NestedBadge);
|
||||
preExistingFixture.detectChanges();
|
||||
|
||||
expect(preExistingFixture.nativeElement.querySelectorAll('.mat-badge-content').length).toBe(2);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
/** Test component that contains a MatBadge. */
|
||||
@@ -214,3 +230,27 @@ class BadgeTestApp {
|
||||
badgeDescription: string;
|
||||
badgeDisabled = false;
|
||||
}
|
||||
|
||||
|
||||
@Component({
|
||||
template: `
|
||||
<span matBadge="Hello">
|
||||
home
|
||||
<div class="mat-badge-content">Pre-existing badge</div>
|
||||
</span>
|
||||
`
|
||||
})
|
||||
class PreExistingBadge {
|
||||
}
|
||||
|
||||
|
||||
@Component({
|
||||
template: `
|
||||
<span matBadge="Hello">
|
||||
home
|
||||
<span matBadge="Hi">Something</span>
|
||||
</span>
|
||||
`
|
||||
})
|
||||
class NestedBadge {
|
||||
}
|
||||
|
||||
+18
-1
@@ -177,9 +177,12 @@ export class MatBadge extends _MatBadgeMixinBase implements OnDestroy, CanDisabl
|
||||
const rootNode = this._renderer || this._document;
|
||||
const badgeElement = rootNode.createElement('span');
|
||||
const activeClass = 'mat-badge-active';
|
||||
const contentClass = 'mat-badge-content';
|
||||
|
||||
// Clear any existing badges which may have persisted from a server-side render.
|
||||
this._clearExistingBadges(contentClass);
|
||||
badgeElement.setAttribute('id', `mat-badge-content-${this._id}`);
|
||||
badgeElement.classList.add('mat-badge-content');
|
||||
badgeElement.classList.add(contentClass);
|
||||
badgeElement.textContent = this.content;
|
||||
|
||||
if (this._animationMode === 'NoopAnimations') {
|
||||
@@ -232,4 +235,18 @@ export class MatBadge extends _MatBadgeMixinBase implements OnDestroy, CanDisabl
|
||||
}
|
||||
}
|
||||
|
||||
/** Clears any existing badges that might be left over from server-side rendering. */
|
||||
private _clearExistingBadges(cssClass: string) {
|
||||
const element = this._elementRef.nativeElement;
|
||||
let childCount = element.children.length;
|
||||
|
||||
// Use a reverse while, because we'll be removing elements from the list as we're iterating.
|
||||
while (childCount--) {
|
||||
const currentChild = element.children[childCount];
|
||||
|
||||
if (currentChild.classList.contains(cssClass)) {
|
||||
element.removeChild(currentChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user