fix(icon): clearing all content when inserting a new SVG (#11956)

This commit is contained in:
Kristiyan Kostadinov
2018-06-28 22:12:25 +02:00
committed by Joey Perrott
parent fc15fa2b56
commit 8280a76c6e
2 changed files with 35 additions and 4 deletions
+26
View File
@@ -51,6 +51,7 @@ describe('MatIcon', () => {
IconWithAriaHiddenFalse,
IconWithBindingAndNgIf,
InlineIcon,
SvgIconWithUserContent,
]
});
@@ -397,6 +398,26 @@ describe('MatIcon', () => {
expect(icon.querySelector('svg')).toBeFalsy();
});
it('should keep non-SVG user content inside the icon element', fakeAsync(() => {
iconRegistry.addSvgIcon('fido', trustUrl('dog.svg'));
const fixture = TestBed.createComponent(SvgIconWithUserContent);
const testComponent = fixture.componentInstance;
const iconElement = fixture.debugElement.nativeElement.querySelector('mat-icon');
testComponent.iconName = 'fido';
fixture.detectChanges();
http.expectOne('dog.svg').flush(FAKE_SVGS.dog);
const userDiv = iconElement.querySelector('div');
expect(userDiv).toBeTruthy();
expect(iconElement.textContent.trim()).toContain('Hello');
tick();
}));
});
describe('Icons from HTML string', () => {
@@ -706,3 +727,8 @@ class IconWithBindingAndNgIf {
class InlineIcon {
inline = false;
}
@Component({template: `<mat-icon [svgIcon]="iconName"><div>Hello</div></mat-icon>`})
class SvgIconWithUserContent {
iconName: string | undefined = '';
}
+9 -4
View File
@@ -74,7 +74,6 @@ export const _MatIconMixinBase = mixinColor(MatIconBase);
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MatIcon extends _MatIconMixinBase implements OnChanges, OnInit, CanColor {
/**
* Whether the icon should be inlined, automatically sizing the icon to match the font size of
* the element the icon is contained in.
@@ -199,10 +198,16 @@ export class MatIcon extends _MatIconMixinBase implements OnChanges, OnInit, Can
const layoutElement: HTMLElement = this._elementRef.nativeElement;
const childCount = layoutElement.childNodes.length;
// Remove existing child nodes and add the new SVG element. Note that we can't
// use innerHTML, because IE will throw if the element has a data binding.
// Remove existing non-element child nodes and SVGs, and add the new SVG element. Note that
// we can't use innerHTML, because IE will throw if the element has a data binding.
for (let i = 0; i < childCount; i++) {
layoutElement.removeChild(layoutElement.childNodes[i]);
const child = layoutElement.childNodes[i];
// 1 corresponds to Node.ELEMENT_NODE. We remove all non-element nodes in order to get rid
// of any loose text nodes, as well as any SVG elements in order to remove any old icons.
if (child.nodeType !== 1 || child.nodeName.toLowerCase() === 'svg') {
layoutElement.removeChild(child);
}
}
}