Skip to content

Commit 5e3228f

Browse files
crisbetokara
authored andcommitted
fix(icon): icon element not removed when svgIcon is reset (#6502)
Fixes #6495.
1 parent 5f75939 commit 5e3228f

File tree

2 files changed

+38
-16
lines changed

2 files changed

+38
-16
lines changed

src/lib/icon/icon.spec.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,25 @@ describe('MdIcon', () => {
331331
}).not.toThrow();
332332
});
333333

334+
it('should remove the SVG element from the DOM when the binding is cleared', () => {
335+
mdIconRegistry.addSvgIconSet(trust('arrow-set.svg'));
336+
337+
let fixture = TestBed.createComponent(IconFromSvgName);
338+
339+
const testComponent = fixture.componentInstance;
340+
const icon = fixture.debugElement.nativeElement.querySelector('md-icon');
341+
342+
testComponent.iconName = 'left-arrow';
343+
fixture.detectChanges();
344+
345+
expect(icon.querySelector('svg')).toBeTruthy();
346+
347+
testComponent.iconName = undefined;
348+
fixture.detectChanges();
349+
350+
expect(icon.querySelector('svg')).toBeFalsy();
351+
});
352+
334353
});
335354

336355
describe('custom fonts', () => {
@@ -418,7 +437,7 @@ class IconWithCustomFontCss {
418437

419438
@Component({template: `<md-icon [svgIcon]="iconName"></md-icon>`})
420439
class IconFromSvgName {
421-
iconName = '';
440+
iconName: string | undefined = '';
422441
}
423442

424443
@Component({template: '<md-icon aria-hidden="false">face</md-icon>'})

src/lib/icon/icon.ts

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -118,24 +118,24 @@ export class MdIcon extends _MdIconMixinBase implements OnChanges, OnInit, CanCo
118118
}
119119
const parts = iconName.split(':');
120120
switch (parts.length) {
121-
case 1:
122-
// Use default namespace.
123-
return ['', parts[0]];
124-
case 2:
125-
return <[string, string]>parts;
126-
default:
127-
throw Error(`Invalid icon name: "${iconName}"`);
121+
case 1: return ['', parts[0]]; // Use default namespace.
122+
case 2: return <[string, string]>parts;
123+
default: throw Error(`Invalid icon name: "${iconName}"`);
128124
}
129125
}
130126

131127
ngOnChanges(changes: SimpleChanges) {
132128
// Only update the inline SVG icon if the inputs changed, to avoid unnecessary DOM operations.
133-
if (changes.svgIcon && this.svgIcon) {
134-
const [namespace, iconName] = this._splitIconName(this.svgIcon);
135-
136-
first.call(this._mdIconRegistry.getNamedSvgIcon(iconName, namespace)).subscribe(
137-
svg => this._setSvgElement(svg),
138-
(err: Error) => console.log(`Error retrieving icon: ${err.message}`));
129+
if (changes.svgIcon) {
130+
if (this.svgIcon) {
131+
const [namespace, iconName] = this._splitIconName(this.svgIcon);
132+
133+
first.call(this._mdIconRegistry.getNamedSvgIcon(iconName, namespace)).subscribe(
134+
svg => this._setSvgElement(svg),
135+
(err: Error) => console.log(`Error retrieving icon: ${err.message}`));
136+
} else {
137+
this._clearSvgElement();
138+
}
139139
}
140140

141141
if (this._usingFontIcon()) {
@@ -156,6 +156,11 @@ export class MdIcon extends _MdIconMixinBase implements OnChanges, OnInit, CanCo
156156
}
157157

158158
private _setSvgElement(svg: SVGElement) {
159+
this._clearSvgElement();
160+
this._renderer.appendChild(this._elementRef.nativeElement, svg);
161+
}
162+
163+
private _clearSvgElement() {
159164
const layoutElement = this._elementRef.nativeElement;
160165
const childCount = layoutElement.childNodes.length;
161166

@@ -164,8 +169,6 @@ export class MdIcon extends _MdIconMixinBase implements OnChanges, OnInit, CanCo
164169
for (let i = 0; i < childCount; i++) {
165170
this._renderer.removeChild(layoutElement, layoutElement.childNodes[i]);
166171
}
167-
168-
this._renderer.appendChild(layoutElement, svg);
169172
}
170173

171174
private _updateFontIconClasses() {

0 commit comments

Comments
 (0)