Repository navigation
bug: ion-radio reflects value to the attribute, destroying non-string values #31394
Description
Ionic Framework Version
- v9.x
(Not present in v8.8.19.)
Current Behavior
ion-radio's value property is now reflected to the value attribute. Because an attribute is a string, any non-string value is round-tripped through the attribute and destroyed:
| assignment | v8.8.19 | v9.0.0 |
|---|---|---|
radio.value = false |
prop=false, attr=null |
prop=false, attr="ion-rb-0" |
radio.value = true |
prop=true, attr=null |
prop="", attr="" |
click the radio → group.value |
true |
"" |
A boolean true reflects as the empty attribute value="" (boolean attribute semantics), and the attribute-changed callback then parses it back into the property as "". The radio still renders as visually checked, so the UI looks correct while ion-radio-group's value — and therefore any framework binding — is silently wrong.
This also conflicts with the documented compareWith property, which exists specifically so that ion-radio values can be objects.
Expected Behavior
value should keep whatever value it was assigned, as in v8. Reflecting an any-typed property to an attribute is lossy and should not happen.
Steps to Reproduce
ionic start radioValue blank --type=vue(framework is irrelevant — this reproduces on bare web components).- Install
@ionic/core@9.0.0. - Render:
<ion-radio-group id="group">
<ion-radio id="r-false">Public</ion-radio>
<ion-radio id="r-true">Restricted</ion-radio>
</ion-radio-group>- After the components hydrate, run:
document.getElementById('r-false').value = false
document.getElementById('r-true').value = true
// v8: true / null v9: "" / ""
console.log(document.getElementById('r-true').value,
document.getElementById('r-true').getAttribute('value'))- Click the second radio and read
document.getElementById('group').value.
Actual (v9): ""
Expected: true
Code Reproduction URL
No Stackblitz link, sorry — but the reproduction above needs no framework at all: two <ion-radio> elements, two property assignments and a console.log. It reproduces on bare @ionic/core and flips purely on the version. Happy to put it on Stackblitz if that would help triage.
Ionic Info
Ionic:
Ionic CLI : 7.2.1
Ionic Framework : @ionic/vue 9.0.0
Capacitor:
Capacitor CLI : 8.5.0
@capacitor/android : 8.5.0
@capacitor/core : 8.5.0
@capacitor/ios : 8.5.0
System:
NodeJS : v26.7.0
npm : 11.19.0
OS : macOS
Additional Information
Cause
The Stencil member flags for ion-radio's value changed between versions (@ionic/core/components, minified proxy metadata):
-"ion-radio",{color:[513],name:[1],disabled:[4],value:[8],labelPlacement:[1,"label-placement"],…}
+"ion-radio",{color:[513],name:[1],disabled:[4],value:[520],labelPlacement:[1,"label-placement"],…}8 is MEMBER_FLAGS.Any; 520 is 512 | 8, i.e. ReflectAttr | Any. So @Prop() on value gained reflect: true.
The interaction with connectedCallback makes the false case odd too:
connectedCallback() {
if (this.value === undefined) { this.value = this.inputId }
…
}which is why a falsy value leaves the generated ion-rb-N id in the reflected attribute.
I scanned every component's proxy metadata across 8.8.19 → 9.0.0: ion-radio.value is the only prop that gained the reflect bit, so reverting it should be low-risk.
Suggested fix
Drop reflect: true from ion-radio's value prop (restore value:[8]). We worked around it by giving our radios string values, which is arguably the more idiomatic choice anyway — but the reflect is still lossy for anyone relying on boolean, number or compareWith object values.
Impact
Any ion-radio with a non-string value breaks silently — the radio appears selected while the bound model receives "". In our app this hid a whole conditional section (v-if on a boolean bound to the radio group) and failed 3 E2E tests, with a misleading symptom: the element that should have appeared "was never found".
Found while upgrading one app from 8.8.19 to 9.0.0; two more regressions from the same release: #31392 and #31393, both in @ionic/vue's class syncing.
Activity
chore(deps): update stencil/core to 4.44.2 and vue-output-target to 0…
ShaneK commentedon Aug 26, 2026
Thanks for your report! This has been fixed in v9.0.1!
ionitron-bot commentedon Sep 25, 2026
Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.