Which @angular/* package(s) are the source of the bug?
forms
Is this a regression?
No
Description
When using the new Signal Forms [formField] directive on a <mat-radio-group> that is located inside a cdkDragList, the visual selection of the radio button is cleared when the item is dragged and dropped.
This occurs because cdkDragDrop detaches and moves the DOM node. During this DOM movement, the browser natively wipes the <input type="radio"> selection if the name attributes are not stable and globally unique.
By default, Signal Forms assign a name based on the array path/index (e.g., form0.myArray.0). While developers can usually bypass browser radio-group collisions by binding a unique model ID to [name]="item().id", the [formField] directive's internal host bindings silently swallow/overwrite custom dynamic [name] bindings during change detection.
Expected behavior:
A developer should be able to explicitly bind a dynamic [name] attribute on a mat-radio-group to provide stable, unique names to the underlying inputs, bypassing the [formField] index-based default.
Dragging and dropping an item within a Form Array should retain its visual checked state.
Actual behavior:
The [formField] directive ignores the custom [name] binding and applies array-index-based names (which Material propagates to the hidden native <input type="radio"> elements).
When the array is re-ordered on drop, the DOM node is moved, and the item's index path changes. The browser natively clears the radio selection because the underlying native input's name attribute isn't tied to a stable ID.
The UI empties, even though the Signal Form's model data retains the correct valid state.
Technical Root Cause & Workaround:
The issue stems from a compilation collision. [formField] manages the name via an internal host binding during change detection, which overrides user-provided dynamic [name] properties.
To currently work around this, developers must write a custom directive using afterEveryRender to manually query the native input[type="radio"] DOM nodes and forcefully overwrite the name attribute to a stable ID immediately after Angular finishes its change detection cycles.
Please provide a link to a minimal reproduction of the bug
https://stackblitz.com/edit/ibnasztc?file=src%2Fexample%2Fitem-form.component.ts
Please provide the exception or error you saw
Please provide the environment you discovered this bug in (run ng version)
Angular CLI : 21.2.15
Angular : 21.2.17
Node.js : 22.22.2
Package Manager : npm 10.9.7
Operating System : linux x64
┌───────────────────────────────────┬───────────────────┬───────────────────┐
│ Package │ Installed Version │ Requested Version │
├───────────────────────────────────┼───────────────────┼───────────────────┤
│ @angular-devkit/build-angular │ 21.2.16 │ ^21.2.16 │
│ @angular/animations │ 21.2.17 │ ^21.2.17 │
│ @angular/cdk │ 21.2.14 │ ^21.2.14 │
│ @angular/cli │ 21.2.15 │ ^21.2.15 │
│ @angular/common │ 21.2.17 │ ^21.2.17 │
│ @angular/compiler │ 21.2.17 │ ^21.2.17 │
│ @angular/compiler-cli │ 21.2.17 │ ^21.2.17 │
│ @angular/core │ 21.2.17 │ ^21.2.17 │
│ @angular/elements │ 21.2.17 │ ^21.2.17 │
│ @angular/forms │ 21.2.17 │ ^21.2.17 │
│ @angular/material │ 21.2.14 │ ^21.2.14 │
│ @angular/platform-browser │ 21.2.17 │ ^21.2.17 │
│ @angular/platform-browser-dynamic │ 21.2.17 │ ^21.2.17 │
│ @angular/router │ 21.2.17 │ ^21.2.17 │
│ rxjs │ 7.8.2 │ ^7.8.2 │
│ typescript │ 5.9.3 │ 5.9.3 │
│ zone.js │ 0.15.1 │ ~0.15.1 │
└───────────────────────────────────┴───────────────────┴───────────────────┘
Anything else?
No response
Which @angular/* package(s) are the source of the bug?
forms
Is this a regression?
No
Description
When using the new Signal Forms
[formField]directive on a<mat-radio-group>that is located inside acdkDragList, the visual selection of the radio button is cleared when the item is dragged and dropped.This occurs because
cdkDragDropdetaches and moves the DOM node. During this DOM movement, the browser natively wipes the<input type="radio">selection if the name attributes are not stable and globally unique.By default, Signal Forms assign a
namebased on the array path/index (e.g.,form0.myArray.0). While developers can usually bypass browser radio-group collisions by binding a unique model ID to[name]="item().id", the[formField]directive's internal host bindings silently swallow/overwrite custom dynamic [name] bindings during change detection.Expected behavior:
A developer should be able to explicitly bind a dynamic
[name]attribute on amat-radio-groupto provide stable, unique names to the underlying inputs, bypassing the[formField]index-based default.Dragging and dropping an item within a Form Array should retain its visual checked state.
Actual behavior:
The
[formField]directive ignores the custom[name]binding and applies array-index-based names (which Material propagates to the hidden native<input type="radio">elements).When the array is re-ordered on drop, the DOM node is moved, and the item's index path changes. The browser natively clears the radio selection because the underlying native input's name attribute isn't tied to a stable ID.
The UI empties, even though the Signal Form's model data retains the correct valid state.
Technical Root Cause & Workaround:
The issue stems from a compilation collision.
[formField]manages thenamevia an internal host binding during change detection, which overrides user-provided dynamic[name]properties.To currently work around this, developers must write a custom directive using
afterEveryRenderto manually query the nativeinput[type="radio"]DOM nodes and forcefully overwrite the name attribute to a stable ID immediately after Angular finishes its change detection cycles.Please provide a link to a minimal reproduction of the bug
https://stackblitz.com/edit/ibnasztc?file=src%2Fexample%2Fitem-form.component.ts
Please provide the exception or error you saw
Please provide the environment you discovered this bug in (run
ng version)Anything else?
No response