diff --git a/devtools/projects/ng-devtools-backend/src/lib/client-event-subscribers.ts b/devtools/projects/ng-devtools-backend/src/lib/client-event-subscribers.ts
index b89bde1aa960..32d0df8df252 100644
--- a/devtools/projects/ng-devtools-backend/src/lib/client-event-subscribers.ts
+++ b/devtools/projects/ng-devtools-backend/src/lib/client-event-subscribers.ts
@@ -51,7 +51,7 @@ import {ComponentTreeNode} from './interfaces';
import {ngDebugDependencyInjectionApiIsSupported} from './ng-debug-api/ng-debug-api';
import {setConsoleReference} from './set-console-reference';
import {serializeDirectiveState} from './state-serializer/state-serializer';
-import {runOutsideAngular} from './utils';
+import {runOutsideAngular, unwrapSignal} from './utils';
import {DirectiveForestHooks} from './hooks/hooks';
export const subscribeToClientEvents = (
@@ -194,7 +194,7 @@ const getNestedPropertiesCallback =
}
let data = current.instance;
for (const prop of propPath) {
- data = data[prop];
+ data = unwrapSignal(data[prop]);
if (!data) {
console.error('Cannot access the properties', propPath, 'of', node);
}
diff --git a/devtools/projects/ng-devtools-backend/src/lib/state-serializer/serialized-descriptor-factory.ts b/devtools/projects/ng-devtools-backend/src/lib/state-serializer/serialized-descriptor-factory.ts
index 67311d761a22..e25266d781ab 100644
--- a/devtools/projects/ng-devtools-backend/src/lib/state-serializer/serialized-descriptor-factory.ts
+++ b/devtools/projects/ng-devtools-backend/src/lib/state-serializer/serialized-descriptor-factory.ts
@@ -325,11 +325,11 @@ function getLevelDescriptorValue(
const isReadonly = isSignal(prop);
switch (type) {
case PropType.Array:
- return prop.map((_: any, idx: number) =>
+ return value.map((_: any, idx: number) =>
continuation(value, idx, isReadonly, currentLevel + 1, level),
);
case PropType.Object:
- return getKeys(prop).reduce(
+ return getKeys(value).reduce(
(accumulator, propName) => {
if (!ignoreList.has(propName)) {
accumulator[propName] = continuation(
diff --git a/devtools/projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/directive-forest/directive-forest.component.html b/devtools/projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/directive-forest/directive-forest.component.html
index 9c390af10847..dee01c775974 100644
--- a/devtools/projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/directive-forest/directive-forest.component.html
+++ b/devtools/projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/directive-forest/directive-forest.component.html
@@ -21,53 +21,57 @@
(mouseleave)="removeHighlight()"
[style.padding-left]="15 + 15 * node.level + 'px'"
>
-
- @if (node.expandable) {
-
- }
-
{{ node.name }}
-
- @if (node.directives) {
-
[{{ node.directives }}]
- }
- @if (isSelected(node)) {
-
== $ng0
- }
-
- @switch(node.hydration?.status) {
- @case('hydrated') {
-
water_drop
+
+ @if (node.expandable) {
+
+
}
- @case('skipped') {
- invert_colors_off
+ {{ node.name }}
+
+ @if (node.directives) {
+ [{{ node.directives }}]
}
- @case('mismatched') {
- error_outline
+ @if (isSelected(node)) {
+ == $ng0
}
- }
-
- @if(node.hydration?.status === 'mismatched' && (node.hydration.expectedNodeDetails || node.hydration.actualNodeDetails)) {
-
- @if(node.hydration.expectedNodeDetails) {
-
Expected Dom:
-
{{node.hydration.expectedNodeDetails}}
- }
- @if(node.hydration.actualNodeDetails) {
-
Actual Dom:
-
{{node.hydration.actualNodeDetails}}
+
+ @switch (node.hydration?.status) {
+ @case ('hydrated') {
+
water_drop
+ }
+ @case ('skipped') {
+
invert_colors_off
+ }
+ @case ('mismatched') {
+
error_outline
+ }
}
- }
+ @if (
+ treeControl.isExpanded(node) &&
+ node.hydration?.status === 'mismatched' &&
+ (node.hydration.expectedNodeDetails || node.hydration.actualNodeDetails)
+ ) {
+
+ @if (node.hydration.expectedNodeDetails) {
+
Expected Dom:
+
{{node.hydration.expectedNodeDetails}}
+ }
+ @if (node.hydration.actualNodeDetails) {
+
Actual Dom:
+
{{node.hydration.actualNodeDetails}}
+ }
+
+ }
-
-
diff --git a/devtools/projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/directive-forest/directive-forest.component.ts b/devtools/projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/directive-forest/directive-forest.component.ts
index 43ecc5b8b2f6..81cd5a6c6976 100644
--- a/devtools/projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/directive-forest/directive-forest.component.ts
+++ b/devtools/projects/ng-devtools/src/lib/devtools-tabs/directive-explorer/directive-forest/directive-forest.component.ts
@@ -16,6 +16,7 @@ import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
+ ElementRef,
EventEmitter,
HostListener,
Input,
@@ -99,11 +100,13 @@ export class DirectiveForestComponent {
readonly itemHeight = 18;
private _initialized = false;
+ private resizeObserver: ResizeObserver;
constructor(
private _tabUpdate: TabUpdate,
private _messageBus: MessageBus,
private _cdr: ChangeDetectorRef,
+ private elementRef: ElementRef,
) {
this.subscribeToInspectorEvents();
this._tabUpdate.tabUpdate$.pipe(takeUntilDestroyed()).subscribe(() => {
@@ -114,6 +117,17 @@ export class DirectiveForestComponent {
});
}
});
+
+ // In some cases there a height changes, we need to recalculate the viewport size.
+ this.resizeObserver = new ResizeObserver(() => {
+ this.viewport.scrollToIndex(0);
+ this.viewport.checkViewportSize();
+ });
+ this.resizeObserver.observe(this.elementRef.nativeElement);
+ }
+
+ ngOnDestroy(): void {
+ this.resizeObserver.disconnect();
}
subscribeToInspectorEvents(): void {
@@ -330,6 +344,10 @@ export class DirectiveForestComponent {
}
}
+ stopPropagation(event: Event): void {
+ event.stopPropagation();
+ }
+
private _findMatchedNodes(): number[] {
const indexesOfMatchedNodes: number[] = [];
for (let i = 0; i < this.dataSource.data.length; i++) {