Skip to content

Commit b7166c9

Browse files
committed
fix(badge): apply view encapsulation attributes on badge element
Since we create the badge content element dynamically, the view encapsulation attributes won't be applied. These changes use the renderer to create the element, which will respect view encapsulation.
1 parent 73d54a4 commit b7166c9

File tree

2 files changed

+34
-4
lines changed

2 files changed

+34
-4
lines changed

src/lib/badge/badge.spec.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {ComponentFixture, TestBed, fakeAsync} from '@angular/core/testing';
2-
import {Component, DebugElement} from '@angular/core';
2+
import {Component, DebugElement, ViewEncapsulation} from '@angular/core';
33
import {By} from '@angular/platform-browser';
44
import {MatBadge, MatBadgeModule} from './index';
55
import {ThemePalette} from '@angular/material/core';
@@ -140,10 +140,27 @@ describe('MatBadge', () => {
140140
expect(classList.contains('mat-badge-hidden')).toBe(false);
141141
});
142142

143+
it('should apply view encapsulation on create badge content', () => {
144+
const badge = badgeNativeElement.querySelector('.mat-badge-content')!;
145+
let encapsulationAttr: Attr | undefined;
146+
147+
for (let i = 0; i < badge.attributes.length; i++) {
148+
if (badge.attributes[i].name.startsWith('_ngcontent-')) {
149+
encapsulationAttr = badge.attributes[i];
150+
break;
151+
}
152+
}
153+
154+
expect(encapsulationAttr).toBeTruthy();
155+
});
156+
143157
});
144158

145159
/** Test component that contains a MatBadge. */
146160
@Component({
161+
// Explicitly set the view encapsulation since we have a test that checks for it.
162+
encapsulation: ViewEncapsulation.Emulated,
163+
styles: ['span { color: hotpink; }'],
147164
template: `
148165
<span [matBadge]="badgeContent"
149166
[matBadgeColor]="badgeColor"

src/lib/badge/badge.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,16 @@
99
import {AriaDescriber} from '@angular/cdk/a11y';
1010
import {coerceBooleanProperty} from '@angular/cdk/coercion';
1111
import {DOCUMENT} from '@angular/common';
12-
import {Directive, ElementRef, Inject, Input, NgZone, OnDestroy, Optional} from '@angular/core';
12+
import {
13+
Directive,
14+
ElementRef,
15+
Inject,
16+
Input,
17+
NgZone,
18+
OnDestroy,
19+
Optional,
20+
Renderer2,
21+
} from '@angular/core';
1322
import {ThemePalette} from '@angular/material/core';
1423

1524

@@ -102,7 +111,9 @@ export class MatBadge implements OnDestroy {
102111
@Optional() @Inject(DOCUMENT) private _document: any,
103112
private _ngZone: NgZone,
104113
private _elementRef: ElementRef<HTMLElement>,
105-
private _ariaDescriber: AriaDescriber) {}
114+
private _ariaDescriber: AriaDescriber,
115+
/** @breaking-change 8.0.0 Make _renderer a required param and remove _document. */
116+
private _renderer?: Renderer2) {}
106117

107118
/** Whether the badge is above the host or not */
108119
isAbove(): boolean {
@@ -132,7 +143,9 @@ export class MatBadge implements OnDestroy {
132143

133144
/** Creates the badge element */
134145
private _createBadgeElement(): HTMLElement {
135-
const badgeElement = this._document.createElement('span');
146+
// @breaking-change 8.0.0 Remove null check for _renderer
147+
const rootNode = this._renderer || this._document;
148+
const badgeElement = rootNode.createElement('span');
136149
const activeClass = 'mat-badge-active';
137150

138151
badgeElement.setAttribute('id', `mat-badge-content-${this._id}`);

0 commit comments

Comments
 (0)