Skip to content

Commit 82072ac

Browse files
authored
refactor: clean up removeChild usages (#23592)
Now that we don't have to support IE11 anymore, we can use `Element.remove` instead of `removeChild`.
1 parent 64ba72f commit 82072ac

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+136
-221
lines changed

src/cdk-experimental/column-resize/resizable.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -108,14 +108,8 @@ export abstract class Resizable<HandleComponent extends ResizeOverlayHandle>
108108
ngOnDestroy(): void {
109109
this.destroyed.next();
110110
this.destroyed.complete();
111-
112-
if (this.inlineHandle) {
113-
this.elementRef.nativeElement!.removeChild(this.inlineHandle);
114-
}
115-
116-
if (this.overlayRef) {
117-
this.overlayRef.dispose();
118-
}
111+
this.inlineHandle?.remove();
112+
this.overlayRef?.dispose();
119113
}
120114

121115
protected abstract getInlineHandleCssClassName(): string;

src/cdk-experimental/column-resize/resize-strategy.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -178,11 +178,8 @@ export class CdkFlexTableResizeStrategy extends ResizeStrategy implements OnDest
178178
}
179179

180180
ngOnDestroy(): void {
181-
// TODO: Use remove() once we're off IE11.
182-
if (this._styleElement && this._styleElement.parentNode) {
183-
this._styleElement.parentNode.removeChild(this._styleElement);
184-
this._styleElement = undefined;
185-
}
181+
this._styleElement?.remove();
182+
this._styleElement = undefined;
186183
}
187184

188185
private _getPropertyValue(cssFriendlyColumnName: string, key: string): string|undefined {

src/cdk-experimental/dialog/dialog.spec.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -877,7 +877,7 @@ describe('Dialog', () => {
877877
describe('focus management', () => {
878878
// When testing focus, all of the elements must be in the DOM.
879879
beforeEach(() => document.body.appendChild(overlayContainerElement));
880-
afterEach(() => document.body.removeChild(overlayContainerElement));
880+
afterEach(() => overlayContainerElement.remove());
881881

882882
it('should focus the first tabbable element of the dialog on open (the default)',
883883
fakeAsync(() => {
@@ -971,7 +971,7 @@ describe('Dialog', () => {
971971
.withContext('Expected that the trigger was refocused after the dialog is closed.')
972972
.toBe('dialog-trigger');
973973

974-
document.body.removeChild(button);
974+
button.remove();
975975
}));
976976

977977
it('should re-focus trigger element inside the shadow DOM when dialog closes', fakeAsync(() => {
@@ -1036,8 +1036,8 @@ describe('Dialog', () => {
10361036
expect(document.activeElement!.id)
10371037
.withContext('Expected focus to stay on the alternate button.').toBe('other-button');
10381038

1039-
body.removeChild(button);
1040-
body.removeChild(otherButton);
1039+
button.remove();
1040+
otherButton.remove();
10411041
}));
10421042

10431043
it('should allow the consumer to shift focus in afterClosed', fakeAsync(() => {
@@ -1069,8 +1069,8 @@ describe('Dialog', () => {
10691069
.withContext('Expected that the trigger was refocused after the dialog is closed.')
10701070
.toBe('input-to-be-focused');
10711071

1072-
document.body.removeChild(button);
1073-
document.body.removeChild(input);
1072+
button.remove();
1073+
input.remove();
10741074
flush();
10751075
}));
10761076

src/cdk-experimental/listbox/listbox.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ export class CdkOption<T = unknown> implements ListKeyManagerOption, Highlightab
174174
private _removeIcons(element: Element) {
175175
// TODO: make this a configurable function that can removed any desired type of node.
176176
for (const icon of Array.from(element.querySelectorAll('mat-icon, .material-icons'))) {
177-
icon.parentNode?.removeChild(icon);
177+
icon.remove();
178178
}
179179
}
180180

src/cdk-experimental/menu/menu-item.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import {Toggler, MENU_AIM, MenuAim} from './menu-aim';
3535
/** Removes all icons from within the given element. */
3636
function removeIcons(element: Element) {
3737
for (const icon of Array.from(element.querySelectorAll('mat-icon, .material-icons'))) {
38-
icon.parentNode?.removeChild(icon);
38+
icon.remove();
3939
}
4040
}
4141

src/cdk-experimental/table-scroll-container/table-scroll-container.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,8 @@ export class CdkTableScrollContainer implements StickyPositioningListener,
6767
}
6868

6969
ngOnDestroy(): void {
70-
// TODO: Use remove() once we're off IE11.
71-
if (this._styleElement?.parentNode) {
72-
this._styleElement.parentNode.removeChild(this._styleElement);
73-
this._styleElement = undefined;
74-
}
70+
this._styleElement?.remove();
71+
this._styleElement = undefined;
7572
}
7673

7774
stickyColumnsUpdated({sizes}: StickyUpdate): void {

src/cdk/a11y/aria-describer/aria-describer.spec.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -214,10 +214,7 @@ describe('AriaDescriber', () => {
214214

215215
// Use `querySelectorAll` with an attribute since `getElementById` will stop at the first match.
216216
expect(document.querySelectorAll(`[id='${MESSAGES_CONTAINER_ID}']`).length).toBe(1);
217-
218-
if (extraContainer.parentNode) {
219-
extraContainer.parentNode.removeChild(extraContainer);
220-
}
217+
extraContainer.remove();
221218
});
222219

223220
it('should not describe messages that match up with the aria-label of the element', () => {

src/cdk/a11y/aria-describer/aria-describer.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,7 @@ export class AriaDescriber implements OnDestroy {
156156
/** Deletes the message element from the global messages container. */
157157
private _deleteMessageElement(key: string|Element) {
158158
const registeredMessage = messageRegistry.get(key);
159-
const messageElement = registeredMessage && registeredMessage.messageElement;
160-
if (messagesContainer && messageElement) {
161-
messagesContainer.removeChild(messageElement);
162-
}
159+
registeredMessage?.messageElement?.remove();
163160
messageRegistry.delete(key);
164161
}
165162

@@ -172,9 +169,7 @@ export class AriaDescriber implements OnDestroy {
172169
// already a container on the page, but we don't have a reference to it. Clear the
173170
// old container so we don't get duplicates. Doing this, instead of emptying the previous
174171
// container, should be slightly faster.
175-
if (preExistingContainer && preExistingContainer.parentNode) {
176-
preExistingContainer.parentNode.removeChild(preExistingContainer);
177-
}
172+
preExistingContainer?.remove();
178173

179174
messagesContainer = this._document.createElement('div');
180175
messagesContainer.id = MESSAGES_CONTAINER_ID;
@@ -193,8 +188,8 @@ export class AriaDescriber implements OnDestroy {
193188

194189
/** Deletes the global messages container. */
195190
private _deleteMessagesContainer() {
196-
if (messagesContainer && messagesContainer.parentNode) {
197-
messagesContainer.parentNode.removeChild(messagesContainer);
191+
if (messagesContainer) {
192+
messagesContainer.remove();
198193
messagesContainer = null;
199194
}
200195
}

src/cdk/a11y/aria-describer/aria-reference.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ describe('AriaReference', () => {
99
});
1010

1111
afterEach(() => {
12-
document.body.removeChild(testElement!);
12+
testElement?.remove();
1313
});
1414

1515
it('should be able to append/remove aria reference IDs', () => {

src/cdk/a11y/focus-trap/focus-trap.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,18 +76,12 @@ export class FocusTrap {
7676

7777
if (startAnchor) {
7878
startAnchor.removeEventListener('focus', this.startAnchorListener);
79-
80-
if (startAnchor.parentNode) {
81-
startAnchor.parentNode.removeChild(startAnchor);
82-
}
79+
startAnchor.remove();
8380
}
8481

8582
if (endAnchor) {
8683
endAnchor.removeEventListener('focus', this.endAnchorListener);
87-
88-
if (endAnchor.parentNode) {
89-
endAnchor.parentNode.removeChild(endAnchor);
90-
}
84+
endAnchor.remove();
9185
}
9286

9387
this._startAnchor = this._endAnchor = null;

src/cdk/a11y/high-contrast-mode/high-contrast-mode-detector.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ export class HighContrastModeDetector {
7474
documentWindow.getComputedStyle(testElement) : null;
7575
const computedColor =
7676
(computedStyle && computedStyle.backgroundColor || '').replace(/ /g, '');
77-
this._document.body.removeChild(testElement);
77+
testElement.remove();
7878

7979
switch (computedColor) {
8080
case 'rgb(0,0,0)': return HighContrastMode.WHITE_ON_BLACK;

src/cdk/a11y/interactivity-checker/interactivity-checker.spec.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ describe('InteractivityChecker', () => {
1616
}));
1717

1818
afterEach(() => {
19-
document.body.removeChild(testContainerElement);
19+
testContainerElement.remove();
2020
testContainerElement.innerHTML = '';
2121
});
2222

@@ -529,8 +529,7 @@ describe('InteractivityChecker', () => {
529529
tmpRoot.innerHTML = template;
530530

531531
const element = tmpRoot.firstElementChild!;
532-
533-
tmpRoot.removeChild(element);
532+
element.remove();
534533

535534
if (append) {
536535
appendElements([element]);

src/cdk/a11y/live-announcer/live-announcer.spec.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,7 @@ describe('LiveAnnouncer', () => {
133133
expect(document.body.querySelectorAll('.cdk-live-announcer-element').length)
134134
.withContext('Expected only one live announcer element in the DOM.')
135135
.toBe(1);
136-
137-
if (extraElement.parentNode) {
138-
extraElement.parentNode.removeChild(extraElement);
139-
}
136+
extraElement.remove();
140137
}));
141138

142139
it('should clear any previous timers when a new one is started', fakeAsync(() => {

src/cdk/a11y/live-announcer/live-announcer.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -142,11 +142,8 @@ export class LiveAnnouncer implements OnDestroy {
142142

143143
ngOnDestroy() {
144144
clearTimeout(this._previousTimeout);
145-
146-
if (this._liveElement && this._liveElement.parentNode) {
147-
this._liveElement.parentNode.removeChild(this._liveElement);
148-
this._liveElement = null!;
149-
}
145+
this._liveElement?.remove();
146+
this._liveElement = null!;
150147
}
151148

152149
private _createLiveElement(): HTMLElement {
@@ -156,7 +153,7 @@ export class LiveAnnouncer implements OnDestroy {
156153

157154
// Remove any old containers. This can happen when coming in from a server-side-rendered page.
158155
for (let i = 0; i < previousElements.length; i++) {
159-
previousElements[i].parentNode!.removeChild(previousElements[i]);
156+
previousElements[i].remove();
160157
}
161158

162159
liveEl.classList.add(elementClass);

src/cdk/clipboard/clipboard.spec.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,7 @@ describe('Clipboard', () => {
2828
});
2929

3030
afterEach(() => {
31-
if (focusedInput.parentNode) {
32-
focusedInput.parentNode.removeChild(focusedInput);
33-
}
31+
focusedInput.remove();
3432
});
3533

3634
describe('#beginCopy', () => {
@@ -79,8 +77,7 @@ describe('Clipboard', () => {
7977

8078
clipboard.copy(COPY_CONTENT);
8179
expect(document.activeElement).toBe(svg);
82-
83-
svg.parentNode!.removeChild(svg);
80+
svg.remove();
8481
});
8582

8683
describe('when execCommand fails', () => {

src/cdk/clipboard/pending-copy.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,7 @@ export class PendingCopy {
6767
const textarea = this._textarea;
6868

6969
if (textarea) {
70-
if (textarea.parentNode) {
71-
textarea.parentNode.removeChild(textarea);
72-
}
73-
70+
textarea.remove();
7471
this._textarea = undefined;
7572
}
7673
}

src/cdk/drag-drop/directives/drag.spec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2336,7 +2336,7 @@ expect(item.style.top)
23362336
const preview = document.querySelector('.cdk-drag-preview')! as HTMLElement;
23372337

23382338
expect(preview.parentNode).toBe(fakeDocument.fullscreenElement);
2339-
fakeDocument.fullscreenElement.parentNode!.removeChild(fakeDocument.fullscreenElement);
2339+
fakeDocument.fullscreenElement.remove();
23402340
}));
23412341

23422342
it('should be able to constrain the preview position', fakeAsync(() => {
@@ -5831,7 +5831,7 @@ expect(sourceCanvas.getContext('2d')!
58315831
targetRect.left + 1, targetRect.top + 1);
58325832

58335833
// Remove the extra node after the element was dropped, but before the animation is over.
5834-
extraSibling.parentNode!.removeChild(extraSibling);
5834+
extraSibling.remove();
58355835

58365836
expect(() => {
58375837
flush();
@@ -7286,7 +7286,7 @@ function makeScrollable(
72867286

72877287
return () => {
72887288
scrollTo(0, 0);
7289-
veryTallElement.parentNode!.removeChild(veryTallElement);
7289+
veryTallElement.remove();
72907290
};
72917291
}
72927292

src/cdk/drag-drop/drag-ref.ts

Lines changed: 6 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -485,10 +485,10 @@ export class DragRef<T = any> {
485485
if (this.isDragging()) {
486486
// Since we move out the element to the end of the body while it's being
487487
// dragged, we have to make sure that it's removed if it gets destroyed.
488-
removeNode(this._rootElement);
488+
this._rootElement?.remove();
489489
}
490490

491-
removeNode(this._anchor);
491+
this._anchor?.remove();
492492
this._destroyPreview();
493493
this._destroyPlaceholder();
494494
this._dragDropRegistry.removeDragItem(this);
@@ -606,27 +606,15 @@ export class DragRef<T = any> {
606606

607607
/** Destroys the preview element and its ViewRef. */
608608
private _destroyPreview() {
609-
if (this._preview) {
610-
removeNode(this._preview);
611-
}
612-
613-
if (this._previewRef) {
614-
this._previewRef.destroy();
615-
}
616-
609+
this._preview?.remove();
610+
this._previewRef?.destroy();
617611
this._preview = this._previewRef = null!;
618612
}
619613

620614
/** Destroys the placeholder element and its ViewRef. */
621615
private _destroyPlaceholder() {
622-
if (this._placeholder) {
623-
removeNode(this._placeholder);
624-
}
625-
626-
if (this._placeholderRef) {
627-
this._placeholderRef.destroy();
628-
}
629-
616+
this._placeholder?.remove();
617+
this._placeholderRef?.destroy();
630618
this._placeholder = this._placeholderRef = null!;
631619
}
632620

@@ -1481,16 +1469,6 @@ function clamp(value: number, min: number, max: number) {
14811469
return Math.max(min, Math.min(max, value));
14821470
}
14831471

1484-
/**
1485-
* Helper to remove a node from the DOM and to do all the necessary null checks.
1486-
* @param node Node to be removed.
1487-
*/
1488-
function removeNode(node: Node | null) {
1489-
if (node && node.parentNode) {
1490-
node.parentNode.removeChild(node);
1491-
}
1492-
}
1493-
14941472
/** Determines whether an event is a touch event. */
14951473
function isTouchEvent(event: MouseEvent | TouchEvent): event is TouchEvent {
14961474
// This function is called for every pixel that the user has dragged so we need it to be

src/cdk/overlay/dispatchers/overlay-keyboard-dispatcher.spec.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,7 @@ describe('OverlayKeyboardDispatcher', () => {
8080
dispatchKeyboardEvent(button, 'keydown', ESCAPE);
8181

8282
expect(spy).not.toHaveBeenCalled();
83-
84-
button.parentNode!.removeChild(button);
83+
button.remove();
8584
});
8685

8786
it('should complete the keydown stream on dispose', () => {

0 commit comments

Comments
 (0)