Skip to content

Commit 754ded6

Browse files
authored
fix(module:icon): re-enter Angular zone after icons have been loaded (#7719)
1 parent 726ded3 commit 754ded6

1 file changed

Lines changed: 21 additions & 12 deletions

File tree

components/icon/icon.directive.ts

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -136,23 +136,32 @@ export class NzIconDirective extends IconDirective implements OnInit, OnChanges,
136136
private changeIcon2(): void {
137137
this.setClassName();
138138

139-
// We don't need to re-enter the Angular zone for adding classes or attributes through the renderer.
139+
// The Angular zone is left deliberately before the SVG is set
140+
// since `_changeIcon` spawns asynchronous tasks as promise and
141+
// HTTP calls. This is used to reduce the number of change detections
142+
// while the icon is being loaded dynamically.
140143
this.ngZone.runOutsideAngular(() => {
141144
from(this._changeIcon())
142145
.pipe(takeUntil(this.destroy$))
143146
.subscribe({
144147
next: svgOrRemove => {
145-
// The _changeIcon method would call Renderer to remove the element of the old icon,
146-
// which would call `markElementAsRemoved` eventually,
147-
// so we should call `detectChanges` to tell Angular remove the DOM node.
148-
// #7186
149-
this.changeDetectorRef.detectChanges();
150-
151-
if (svgOrRemove) {
152-
this.setSVGData(svgOrRemove);
153-
this.handleSpin(svgOrRemove);
154-
this.handleRotate(svgOrRemove);
155-
}
148+
// Get back into the Angular zone after completing all the tasks.
149+
// Since we manually run change detection locally, we have to re-enter
150+
// the zone because the change detection might also be run on other local
151+
// components, leading them to handle template functions outside of the Angular zone.
152+
this.ngZone.run(() => {
153+
// The _changeIcon method would call Renderer to remove the element of the old icon,
154+
// which would call `markElementAsRemoved` eventually,
155+
// so we should call `detectChanges` to tell Angular remove the DOM node.
156+
// #7186
157+
this.changeDetectorRef.detectChanges();
158+
159+
if (svgOrRemove) {
160+
this.setSVGData(svgOrRemove);
161+
this.handleSpin(svgOrRemove);
162+
this.handleRotate(svgOrRemove);
163+
}
164+
});
156165
},
157166
error: warn
158167
});

0 commit comments

Comments
 (0)