| title | Forms |
|---|---|
| description | Every form on the page with each field's state and errors, a change timeline, submit explanations and a lint. |
The Forms tab reads the forms of the running page, in development builds only. It covers Signal Forms, reactive forms and template-driven forms. Actions you run from the tab go back to the page and run there.
The sidebar lists each form with its label, its kind (Signal Forms, Reactive or Template-driven) and its error count. When the panel runs inside a page and other tabs report forms, check All pages to include them. If you uncheck All pages while a form from another tab is selected, the details say the form is on another page and offer Show forms from all pages.
Select a form to see its status, whether it is dirty or touched, whether it was submitted or is submitting, and an Error summary.
Click an entry in the Error summary to open that field. The tab switches to the Fields view, opens the field's details and moves focus to them. If the path filter or the chips hide the field, the tab clears them, the filter first and the chips only if the field is still hidden.
A Signal Form that sets experimentalWebMcpTool (with provideExperimentalWebMcpForms()) shows a WebMCP tool block in its details. See WebMCP for the API itself.
| Part | What it shows |
|---|---|
| Name and status | The tool name, and registered or not registered. A name another tool on the page also uses is marked duplicate name. |
| Description | The description the form passes. |
| Inputs | Each input with its type, and which ones the schema marks as required. |
| Blocking fields | When Angular could not infer a schema, each field that is null, undefined, an empty array or an unsupported type. |
| Required changed | Fields whose required changed after registration. Angular reads required once, so agents still see the old one. |
| Recent calls | The last 5 agent calls with time, duration, the input names and the result (submitted, submit failed or threw). |
Agent calls set the value and submit the form. Those changes show in the timeline with the agent origin.
If the app provides provideExperimentalWebMcpForms() but the browser has no modelContext, Angular registers no tool. The block says so instead.
Each field shows its value, status, touched and dirty state, and errors. Extra facts depend on the kind:
- Signal Forms: constraints (
min,max,minLength,maxLength,pattern),required,readonlyandhidden, a pendingdebounce, and disabled reasons. - Reactive and template-driven: whether validators and async validators are attached, the value
reset()goes back to,updateOn, and the boundControlValueAccessor.
Filter by path, or with the Invalid, Dirty, Touched, Disabled and Error not shown chips. If the filters hide every field, click Clear filters to reset the path filter and the chips. Focus returns to the path filter. Hover a field to highlight its input in the page.
Each error says where it comes from:
| Label | Meaning |
|---|---|
| validator | A validator on the control. |
| template attribute | A template attribute, such as required or minlength. |
| cross-field rule | A rule on an ancestor, with the ancestor's path. |
| async | An async validator. |
| parse | The input could not parse the typed text. |
| schema | A Standard Schema, with the path it reported. |
| server | A server or submission error. |
| setErrors | Code set the error with setErrors(). |
Click a field to open its details below the table. Click the field again, or Close, to hide them. From there, set a value, or click Focus, Touch, Revalidate or Store as global. Store as global stores the form as $form, and the field as $control, in the page console.
Recent changes, newest first, each tagged with its origin: user, code, agent (a WebMCP tool call) or devtools. The timeline tracks array items by identity, so moves show as moves. Async validation times show as pending tags. The page keeps the last 200 events, set with limits.formTimeline. Once older events are dropped, the timeline and form-history say how many.
Narrow the list with three filters. An event shows only when it passes all of them.
| Filter | What it matches |
|---|---|
| Filter by field path | Events whose field path contains the text, ignoring case. Press Escape to clear it. |
| Event type | One event type, such as value, status or submit. Lists only the types present. |
| Origin (All, User and so on) | Events from one origin. |
The list shows the latest 100 matching events. When more match, the count next to the filters says so, for example "Showing the latest 100 of 240 events". If the filters hide every event, click Clear filters to reset all three.
Check Record details to add the calling code of each change, validator changes, and component renders per keystroke. It is off by default and applies to the whole page.
What submit does, and why it might do nothing. It also shows what the form sends. Copy test fixture copies a fixture for your tests.
Form bugs and model-aware accessibility checks, each with a fix. For generic accessibility checks, run axe on the page.
A finding about one field shows its path, such as at address.zip. Click the path to open that field, the same way an Error summary entry does: the tab switches to the Fields view, opens the field's details and moves focus to them. Findings about the whole form have no path.
If the devtools server does not answer, the Submit view, the Lint view and the field details say so and offer Try again.
The actions bar works on the selected form:
- Touch all, Revalidate and Focus first invalid.
- Pick field on page: click a field in the app to select it. While picking, the button reads Cancel picking. Press it, or Escape in the panel or the app, to stop. The pick also stops after 12 seconds.
- Snapshot saves the form's values as
s1,s2and so on. Restore puts back the latest one. The button shows its name, like Restore s2. - Reset and Submit.
The overlay reads the forms after change detection and pushes them when they change. It also pushes shortly after each input, change, focusout, submit or reset event. Reactive and template-driven forms also report each change through control.events.
To tell where each error comes from, the devtools run the sync validators of reactive and template-driven fields themselves. They do this only for enabled leaf fields. They reuse the result for up to 5 seconds while the value and the validators stay the same. With Record details on, they run on every report.
The devtools never run async validators. The probe emits no form events, so it does not show up in the timeline.
The devtools call your sync validators. A validator that logs, counts or changes state sees extra calls while the Forms tab is open. The error count in the sidebar shows which forms fail. Click the Invalid chip. Each error says which validator, attribute or rule set it. Click Error not shown to find errors that have no visible message. It explains what submit does. Compare the value with what your API expects. Click Copy test fixture to reproduce it in a test. Save the current values. Type in the app, or set values from the field details. Click Restore s1, then click again to confirm.You can also open a form from its component in the Components tab.
form is a form id like Checkout.form@ab12, or part of its label. path is a dotted field path, like address.city. A literal dot in a control key is written \. and a literal backslash \\, so the control keyed a.b has the path a\.b. An empty key is written \e, so it is never confused with the whole form, whose path is empty. The panel and the tool output show the same escaped form.
| Tool | What it does |
|---|---|
pangular:explain-form-invalid |
Start here. Every invalid or pending form, with each failing field's value, validator, message and touched state. Narrow with path. |
pangular:inspect-forms |
The forms with status and error counts, and WebMCP tool state. With form, the field tree. Narrow with path or onlyInvalid. |
pangular:explain-field |
One field: error sources, skip reasons, pending values, binding, visible errors, and source lines. |
pangular:explain-submit |
What submit does, and why it might do nothing. |
pangular:form-payload |
What the form sends: value against raw value, and unvalidated fields. Narrow with path. |
pangular:form-history |
The change timeline with origins. Returns a marker. |
pangular:form-diff |
The net change since a marker. |
pangular:lint-forms |
Form bugs and accessibility checks. |
pangular:explain-custom-control |
How a field binds to its element, and what is wrong with the binding. |
pangular:export-form |
A JSON snapshot or a test fixture. |
pangular:wait-for-form |
Waits until the form is settled, valid, not pending or submitted. |
| Tool | What it does |
|---|---|
pangular:form-action |
Set, touch, revalidate, reset, submit, focus, snapshot, restore and more. |
pangular:fill-form |
Fills several fields through the inputs, like a user would. Can submit afterwards. |
Agents can loop: inspect, act, wait-for-form, then form-diff from the marker they had. The pangular:forms resource holds every form and recent changes. See Tools.
[redacted]. To mask or unmask a field, see Security.
In the tab, the button turns into Confirm reset, Confirm submit or Confirm restore. Click again to run it. If the selected form changes first, for example because the page destroyed it, the confirmation, the snapshot and the open field are cleared. Agents pass confirm: true for the same actions, and for fill-form with submit.
The actions don't write secret fields unless you unmask them. See Access and redaction. For Signal Forms, they skip hidden, readonly and rule-disabled fields too. They write disabled reactive fields only with force.
experimentalWebMcpTool is experimental in Angular. The overlay wraps modelContext.registerTool when it loads, so it records registrations and calls from then on. The overlay has no hook that runs before your app. For a tool registered earlier, it reads the browser's tool list when the browser offers one (getTools() or listTools()), and the block says registered before the inspector attached. Calls to those tools are not recorded. If the browser offers no tool list, a form that registered before the overlay loaded shows no WebMCP tool block. To see every registration and call, register the form after the overlay loads, for example on a route you open later. The overlay links a tool to its form by its input schema, or by the form an agent call submits. A tool it cannot link shows in the inspect-forms output under WebMCP.
Without a browser that provides modelContext, Angular registers no tool. The Angular Travel demo adds a stand-in navigator.modelContext in development when the browser has none. Its Signal Forms example on /examples/forms registers a sign_up tool:
/, so the overlay loads before the form registers its tool.
Go to DevTools Lab, then Forms. The WebMCP tool block of SignalFormExample.signup shows sign_up as registered.
Click Fill as an agent. The call shows under Recent calls, and its changes show in the timeline with the agent origin.
If you load /examples/forms directly, the form registers before the overlay loads. The block then says registered before the inspector attached, and the call is not recorded. In a browser with its own modelContext, the demo uses it, and Fill as an agent asks you to call sign_up from your agent.
The agent tools cut answers about large forms, so one form cannot fill an agent's context. A cut answer says how many fields or lines it left out and how to narrow the answer, for example with path, form or a later since marker. See Tools for each limit.
The page keeps up to 20 snapshots, and a reload clears them. Restore fails when the form's shape has changed, and it keeps the current value of secret fields.
The current tab has no form yet. Click Show forms from all pages to see forms from other tabs. The timeline records callers only with Record details checked. No. It reads state and runs sync validators without emitting events. Only the actions write. Open a form from the component that owns it. What is redacted, and how to mask a field. Every tool a coding agent can call. The script that reports the live page.