From 2b9c1944e1072e14a3f1fc495643b2c8af8a676e Mon Sep 17 00:00:00 2001 From: Kam Date: Fri, 25 Sep 2026 15:05:00 +0300 Subject: [PATCH 1/4] feat(forms): add support for various form types and enhance devtools integration - Introduced new forms example page showcasing Signal Forms, Reactive Forms, and Template-driven Forms. - Implemented form validation and error handling in Reactive and Signal Forms. - Enhanced the ng-devtools overlay to track form events and states, including highlighting form fields. - Added new RPC methods for inspecting forms and reporting their states. - Updated routing to include the new forms example and adjusted navigation links accordingly. - Improved styling for form components to enhance user experience. --- README.md | 49 +- app/src/app.ts | 33 +- app/src/pages/dashboard.ts | 14 +- app/src/pages/forms-inspector.ts | 642 ++++++++++ ...=> browser-agent-rpc-BXhoSh1z-C4PjrSs6.js} | 2 +- extension/ui/assets/index-BUkjK2_k.js | 896 ------------- extension/ui/assets/index-KMcCjGxa.js | 1141 +++++++++++++++++ extension/ui/index.html | 2 +- ...=> browser-agent-rpc-BXhoSh1z-C4PjrSs6.js} | 2 +- .../dist/assets/index-BUkjK2_k.js | 896 ------------- .../dist/assets/index-KMcCjGxa.js | 1141 +++++++++++++++++ packages/ng-devtools-assets/dist/index.html | 2 +- .../src/__tests__/forms-real.test.ts | 122 ++ .../src/__tests__/forms-tools.test.ts | 270 ++++ .../ng-devtools/src/__tests__/forms.test.ts | 922 +++++++++++++ packages/ng-devtools/src/devframe.ts | 124 ++ packages/ng-devtools/src/forms.ts | 885 +++++++++++++ packages/ng-devtools/src/overlay.ts | 246 +++- packages/ng-devtools/src/rpc/forms-tools.ts | 243 ++++ src/app/examples/examples-overview.ts | 8 +- src/app/examples/examples.routes.ts | 5 + src/app/examples/examples.ts | 1 + src/app/examples/forms-example.css | 72 ++ src/app/examples/forms-example.ts | 36 + src/app/examples/reactive-form-example.ts | 170 +++ src/app/examples/signal-form-example.ts | 152 +++ src/app/examples/template-form-example.ts | 94 ++ src/main.ts | 19 +- 28 files changed, 6347 insertions(+), 1842 deletions(-) create mode 100644 app/src/pages/forms-inspector.ts rename extension/ui/assets/{browser-agent-rpc-BXhoSh1z-DT7_jkxB.js => browser-agent-rpc-BXhoSh1z-C4PjrSs6.js} (93%) delete mode 100644 extension/ui/assets/index-BUkjK2_k.js create mode 100644 extension/ui/assets/index-KMcCjGxa.js rename packages/ng-devtools-assets/dist/assets/{browser-agent-rpc-BXhoSh1z-DT7_jkxB.js => browser-agent-rpc-BXhoSh1z-C4PjrSs6.js} (93%) delete mode 100644 packages/ng-devtools-assets/dist/assets/index-BUkjK2_k.js create mode 100644 packages/ng-devtools-assets/dist/assets/index-KMcCjGxa.js create mode 100644 packages/ng-devtools/src/__tests__/forms-real.test.ts create mode 100644 packages/ng-devtools/src/__tests__/forms-tools.test.ts create mode 100644 packages/ng-devtools/src/__tests__/forms.test.ts create mode 100644 packages/ng-devtools/src/forms.ts create mode 100644 packages/ng-devtools/src/rpc/forms-tools.ts create mode 100644 src/app/examples/forms-example.css create mode 100644 src/app/examples/forms-example.ts create mode 100644 src/app/examples/reactive-form-example.ts create mode 100644 src/app/examples/signal-form-example.ts create mode 100644 src/app/examples/template-form-example.ts diff --git a/README.md b/README.md index 6256432..231fbaa 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ Inspect Angular component trees, signals, dependency injection, and routes — a - **DI inspector** — browse the injector hierarchy (element and environment) with providers at each level (Angular 17+) - **Route inspector** — list registered routes from source - **NgRx Store inspector** — detect `@ngrx/store` (actions, reducers, effects, selectors) and `@ngrx/signals` (`signalStore`, `signalState`, `signalMethod`) patterns from source; live state & action log via Redux DevTools protocol +- **Forms inspector** — every form on the page (Signal Forms, reactive and template-driven) with each field's value, status, touched/dirty state and readable errors, plus a timeline of recent changes; hover a field to highlight its input - **Build metadata** — Angular version, TypeScript version, SSR status - **In-page popup** — floating devtools panel with dock modes (float, bottom, right), drag, resize, and localStorage persistence - **Agent-native** — all inspectors exposed as MCP tools and resources @@ -91,26 +92,40 @@ When embedded in Express, the MCP endpoint is also available over HTTP at `/__ng MCP clients see these with an underscore, as `ng-devtools_get-routes`. -| Tool | Description | -| ------------------------------- | ----------------------------------------------------------- | -| `ng-devtools:get-routes` | List Angular routes from source | -| `ng-devtools:get-components` | Discover components and directives, with inputs and outputs | -| `ng-devtools:get-signals` | Signal declarations from source | -| `ng-devtools:get-providers` | DI providers from source | -| `ng-devtools:build-meta` | Angular/TS versions, SSR status | -| `ng-devtools:highlight` | Highlight a component in the page | -| `ng-devtools:inspect-signals` | Signal graph a connected page reported | -| `ng-devtools:inspect-providers` | Injector tree a connected page reported | -| `ng-devtools:get-ngrx-store` | Scan source for NgRx store patterns | +| Tool | Description | +| ---------------------------------- | ----------------------------------------------------------- | +| `ng-devtools:get-routes` | List Angular routes from source | +| `ng-devtools:get-components` | Discover components and directives, with inputs and outputs | +| `ng-devtools:get-signals` | Signal declarations from source | +| `ng-devtools:get-providers` | DI providers from source | +| `ng-devtools:build-meta` | Angular/TS versions, SSR status | +| `ng-devtools:highlight` | Highlight a component in the page | +| `ng-devtools:inspect-signals` | Signal graph a connected page reported | +| `ng-devtools:inspect-providers` | Injector tree a connected page reported | +| `ng-devtools:get-ngrx-store` | Scan source for NgRx store patterns | +| `ng-devtools:inspect-forms` | Forms on the page with every field's state and errors | +| `ng-devtools:explain-form-invalid` | Which fields make a form invalid, and why | + +#### Forms + +The Forms tab and the forms tools read Signal Forms, reactive forms and template-driven forms from the running page, in development builds only. Signal Forms need Angular 21 or later. The live change timeline for reactive and template-driven forms uses `control.events` (Angular 18+); on Angular 17 changes are picked up every few seconds instead, without submit and reset events. + +- Each field shows its value, status, touched/dirty state and errors, plus: Signal Forms constraints (`min`, `max`, `minLength`, `maxLength`, `pattern`), a pending `debounce`, `submitting`, and disabled reasons; for reactive and template-driven forms, whether validators and async validators are attached, the value `reset()` goes back to, `updateOn`, and the bound `ControlValueAccessor`. +- `ng-devtools:explain-form-invalid` is the tool to reach for first: without arguments it lists every form that is invalid or waiting on async validation, with each failing field's current value, the validator that failed, its message and whether it was touched. Pass `form` (an id like `form-1`, or part of a label like `SignupComponent`) to explain one form. +- `ng-devtools:inspect-forms` lists the forms with their status and error counts. Pass `form` for a field tree, plus `path` (e.g. `address.city`), `onlyInvalid` or `includeValues: false` to narrow it down. +- Both tools note when the page last reported, so an agent can tell when the data is stale. + +Form values leave the page: they are sent to the devtools server, shown in the Forms tab and returned to agents. Values of password fields, fields with a password, one-time-code or credit-card `autocomplete`, and fields whose name looks secret (password, token, card, cvv and similar) are replaced with `[redacted]`. Other values are sent as they are, so keep real credentials out of forms you inspect, and don't expose the dev server beyond localhost. #### Agent Resources -| Resource | Content | -| ---------------------------- | ---------------------------- | -| `ng-devtools:component-tree` | Live component hierarchy | -| `ng-devtools:signal-graph` | Signal dependency graph | -| `ng-devtools:injector-tree` | DI injector hierarchy | -| `ng-devtools:ngrx-store` | Live NgRx state & action log | +| Resource | Content | +| ---------------------------- | ----------------------------- | +| `ng-devtools:component-tree` | Live component hierarchy | +| `ng-devtools:signal-graph` | Signal dependency graph | +| `ng-devtools:injector-tree` | DI injector hierarchy | +| `ng-devtools:ngrx-store` | Live NgRx state & action log | +| `ng-devtools:forms` | Live forms and recent changes | ### Vite DevTools Dock diff --git a/app/src/app.ts b/app/src/app.ts index 4d4801e..9698ecc 100644 --- a/app/src/app.ts +++ b/app/src/app.ts @@ -6,15 +6,24 @@ import { RouteInspector } from './pages/route-inspector'; import { SignalInspector } from './pages/signal-inspector'; import { DiInspector } from './pages/di-inspector'; import { StoreInspector } from './pages/store-inspector'; +import { FormsInspector } from './pages/forms-inspector'; -type Tab = 'dashboard' | 'components' | 'routes' | 'signals' | 'injectors' | 'store'; +type Tab = 'dashboard' | 'components' | 'routes' | 'signals' | 'injectors' | 'store' | 'forms'; @Component({ selector: 'app-root', - imports: [Dashboard, ComponentTree, RouteInspector, SignalInspector, DiInspector, StoreInspector], + imports: [ + Dashboard, + ComponentTree, + RouteInspector, + SignalInspector, + DiInspector, + StoreInspector, + FormsInspector, + ], template: `
-
+

Angular DevTools -

+