Skip to content

Commit 26e47cc

Browse files
committed
WIP: attempt to use MutationObserver to observe table rows
1 parent 0998216 commit 26e47cc

File tree

1 file changed

+46
-11
lines changed

1 file changed

+46
-11
lines changed

src/cdk-experimental/popover-edit/table-directives.ts

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,18 @@ import {FocusTrap} from '@angular/cdk/a11y';
99
import {OverlayRef, OverlaySizeConfig, PositionStrategy} from '@angular/cdk/overlay';
1010
import {TemplatePortal} from '@angular/cdk/portal';
1111
import {
12-
afterRender,
12+
afterNextRender,
1313
AfterViewInit,
1414
Directive,
1515
ElementRef,
1616
EmbeddedViewRef,
17+
inject,
18+
ListenerOptions,
1719
NgZone,
1820
OnDestroy,
21+
Renderer2,
1922
TemplateRef,
2023
ViewContainerRef,
21-
inject,
22-
Renderer2,
23-
ListenerOptions,
2424
} from '@angular/core';
2525
import {merge, Observable, Subject} from 'rxjs';
2626
import {
@@ -35,8 +35,10 @@ import {
3535
withLatestFrom,
3636
} from 'rxjs/operators';
3737

38+
import {_bindEventWithOptions} from '@angular/cdk/platform';
3839
import {CELL_SELECTOR, EDIT_PANE_CLASS, EDIT_PANE_SELECTOR, ROW_SELECTOR} from './constants';
3940
import {EditEventDispatcher, HoverContentState} from './edit-event-dispatcher';
41+
import {EditRef} from './edit-ref';
4042
import {EditServices} from './edit-services';
4143
import {FocusDispatcher} from './focus-dispatcher';
4244
import {
@@ -45,8 +47,6 @@ import {
4547
FocusEscapeNotifierFactory,
4648
} from './focus-escape-notifier';
4749
import {closest} from './polyfill';
48-
import {EditRef} from './edit-ref';
49-
import {_bindEventWithOptions} from '@angular/cdk/platform';
5050

5151
/**
5252
* Describes the number of columns before and after the originating cell that the
@@ -80,11 +80,24 @@ export class CdkEditable implements AfterViewInit, OnDestroy {
8080

8181
protected readonly destroyed = new Subject<void>();
8282

83-
private _rendered = new Subject();
83+
private _rowsRendered = new Subject();
84+
85+
private _rowMutationObserver = globalThis.MutationObserver
86+
? new globalThis.MutationObserver(mutations => {
87+
if (mutations.some(m => this._isRowMutation(m))) {
88+
this._rowsRendered.next();
89+
}
90+
})
91+
: null;
8492

8593
constructor() {
86-
afterRender(() => {
87-
this._rendered.next();
94+
// Keep track of when the rendered rows changes.
95+
afterNextRender(() => {
96+
this._rowsRendered.next();
97+
this._rowMutationObserver?.observe(this.elementRef.nativeElement, {
98+
childList: true,
99+
subtree: true,
100+
});
88101
});
89102
}
90103

@@ -95,7 +108,29 @@ export class CdkEditable implements AfterViewInit, OnDestroy {
95108
ngOnDestroy(): void {
96109
this.destroyed.next();
97110
this.destroyed.complete();
98-
this._rendered.complete();
111+
this._rowMutationObserver?.disconnect();
112+
}
113+
114+
private _isRowMutation(mutation: MutationRecord): boolean {
115+
for (let i = 0; i < mutation.addedNodes.length; i++) {
116+
const el = mutation.addedNodes[i];
117+
if (!(el instanceof HTMLElement)) {
118+
continue;
119+
}
120+
if (el.matches(ROW_SELECTOR)) {
121+
return true;
122+
}
123+
}
124+
for (let i = 0; i < mutation.removedNodes.length; i++) {
125+
const el = mutation.removedNodes[i];
126+
if (!(el instanceof HTMLElement)) {
127+
continue;
128+
}
129+
if (el.matches(ROW_SELECTOR)) {
130+
return true;
131+
}
132+
}
133+
return false;
99134
}
100135

101136
private _observableFromEvent<T extends Event>(
@@ -153,7 +188,7 @@ export class CdkEditable implements AfterViewInit, OnDestroy {
153188
// Keep track of rows within the table. This is used to know which rows with hover content
154189
// are first or last in the table. They are kept focusable in case focus enters from above
155190
// or below the table.
156-
this._rendered
191+
this._rowsRendered
157192
.pipe(
158193
// Avoid some timing inconsistencies since Angular v19.
159194
debounceTime(0),

0 commit comments

Comments
 (0)