commit 1c4cd715aba2c9ea159f52bae4c57ae7873fdbb2
parent a3c1803f345d52bc1ae19e5547a629a6677ecd99
Author: Tim Giles <tgiles@mozilla.com>
Date: Tue, 4 Nov 2025 22:04:16 +0000
Bug 1991743 - Add form behavior for SelectControl. r=mkennedy
In order for moz-radio-group to behave correctly when used in a form, we
needed to add the `formAssociated` property to the SelectControl class
and implement `setFormValue` and `formResetCallback`.
Differential Revision: https://phabricator.services.mozilla.com/D269048
Diffstat:
2 files changed, 114 insertions(+), 12 deletions(-)
diff --git a/toolkit/content/tests/widgets/test_moz_input_elems_in_form.html b/toolkit/content/tests/widgets/test_moz_input_elems_in_form.html
@@ -36,6 +36,14 @@
value="checkbox_val"
checked=""
></moz-checkbox>
+ <moz-radio-group name="moz-radio-group" value="radio_val_1">
+ <moz-radio value="radio_val_1"></moz-radio>
+ <moz-radio value="radio_val_2"></moz-radio>
+ </moz-radio-group>
+ <moz-select name="moz-select" value="select_val_1">
+ <moz-option value="select_val_1"></moz-option>
+ <moz-option value="select_val_2"></moz-option>
+ </moz-select>
<moz-toggle
name="moz-toggle"
value="toggle_val"
@@ -61,6 +69,22 @@
checked=""
form="form-attribute-id"
></moz-checkbox>
+ <moz-radio-group
+ name="moz-radio-group"
+ value="radio_val_1"
+ form="form-attribute-id"
+ >
+ <moz-radio value="radio_val_1"></moz-radio>
+ <moz-radio value="radio_val_2"></moz-radio>
+ </moz-radio-group>
+ <moz-select
+ name="moz-select"
+ value="select_val_1"
+ form="form-attribute-id"
+ >
+ <moz-option value="select_val_1"></moz-option>
+ <moz-option value="select_val_2"></moz-option>
+ </moz-select>
<moz-toggle
name="moz-toggle"
value="toggle_val"
@@ -93,6 +117,16 @@
"moz-checkbox, when checked, should have a submitted value"
);
is(
+ formData.get("moz-radio-group"),
+ "radio_val_1",
+ "moz-radio-group should have a submitted value"
+ );
+ is(
+ formData.get("moz-select"),
+ "select_val_1",
+ "moz-select should have a submitted value"
+ );
+ is(
formData.get("moz-toggle"),
"toggle_val",
"moz-toggle should have a submitted value"
@@ -121,11 +155,19 @@
event.preventDefault();
const formData = new FormData(form);
for (let [key, value] of formData) {
- is(
- value,
- "non-default value",
- `${key} should have a non-default submitted value`
- );
+ if (key === "moz-radio-group") {
+ is(
+ value,
+ "radio_val_2",
+ `${key} should have a non-default value`
+ );
+ } else {
+ is(
+ value,
+ "non-default value",
+ `${key} should have a non-default submitted value`
+ );
+ }
}
};
form.addEventListener(
@@ -135,7 +177,11 @@
);
let fieldset = form.querySelector("moz-fieldset");
for (let c of fieldset.children) {
- c.value = "non-default value";
+ if (c.name === "moz-radio-group") {
+ c.value = "radio_val_2";
+ } else {
+ c.value = "non-default value";
+ }
}
// Wait for the input elements to update before clicking the
@@ -198,6 +244,16 @@
"moz-checkbox should reset to default value"
);
is(
+ formData.get("moz-radio-group"),
+ document.querySelector("moz-radio-group").getAttribute("value"),
+ "moz-radio-group should reset to default value"
+ );
+ is(
+ formData.get("moz-select"),
+ document.querySelector("moz-select").getAttribute("value"),
+ "moz-select should reset to default value"
+ );
+ is(
formData.get("moz-toggle"),
document.querySelector("moz-toggle").getAttribute("value"),
"moz-toggle should reset to default value"
@@ -268,6 +324,16 @@
"moz-checkbox, when checked, should have a submitted value"
);
is(
+ formData.get("moz-radio-group"),
+ "radio_val_1",
+ "moz-radio-group should have a submitted value"
+ );
+ is(
+ formData.get("moz-select"),
+ "select_val_1",
+ "moz-select should have a submitted value"
+ );
+ is(
formData.get("moz-toggle"),
"toggle_val",
"moz-toggle should have a submitted value"
@@ -296,11 +362,19 @@
event.preventDefault();
const formData = new FormData(form);
for (let [key, value] of formData) {
- is(
- value,
- "non-default value",
- `${key} should have a non-default submitted value`
- );
+ if (key === "moz-radio-group") {
+ is(
+ value,
+ "radio_val_2",
+ `${key} should have a non-default value`
+ );
+ } else {
+ is(
+ value,
+ "non-default value",
+ `${key} should have a non-default submitted value`
+ );
+ }
}
};
form.addEventListener(
@@ -310,7 +384,11 @@
);
let fieldset = document.querySelector("div moz-fieldset");
for (let c of fieldset.children) {
- c.value = "non-default value";
+ if (c.name === "moz-radio-group") {
+ c.value = "radio_val_2";
+ } else {
+ c.value = "non-default value";
+ }
}
// Wait for the input elements to update before clicking the
@@ -380,6 +458,16 @@
"moz-checkbox should reset to default value"
);
is(
+ formData.get("moz-radio-group"),
+ document.querySelector("moz-radio-group").getAttribute("value"),
+ "moz-radio-group should reset to default value"
+ );
+ is(
+ formData.get("moz-select"),
+ document.querySelector("moz-select").getAttribute("value"),
+ "moz-select should reset to default value"
+ );
+ is(
formData.get("moz-toggle"),
document.querySelector("moz-toggle").getAttribute("value"),
"moz-toggle should reset to default value"
diff --git a/toolkit/content/widgets/lit-select-control.mjs b/toolkit/content/widgets/lit-select-control.mjs
@@ -39,10 +39,12 @@ const NAVIGATION_DIRECTIONS = {
* expected.
*/
export class SelectControlBaseElement extends MozLitElement {
+ static formAssociated = true;
#childElements;
#value;
#checkedIndex;
#focusedIndex;
+ #internals;
static properties = {
type: { type: String },
@@ -61,6 +63,7 @@ export class SelectControlBaseElement extends MozLitElement {
set value(newValue) {
this.#value = newValue;
+ this.#internals.setFormValue(newValue);
this.childElements.forEach((item, index) => {
let isChecked = this.value === item.value;
item.checked = isChecked;
@@ -136,11 +139,19 @@ export class SelectControlBaseElement extends MozLitElement {
}
return this.#childElements;
}
+ get form() {
+ return this.#internals.form;
+ }
+
+ formResetCallback() {
+ this.value = this.getAttribute("value");
+ }
constructor() {
super();
this.type = "radio";
this.disabled = false;
+ this.#internals = this.attachInternals();
this.addEventListener("blur", e => this.handleBlur(e), true);
this.addEventListener("keydown", e => this.handleKeydown(e));
}
@@ -264,6 +275,9 @@ export class SelectControlBaseElement extends MozLitElement {
item.role = childRole;
});
}
+ if (changedProperties.has("value")) {
+ this.#internals.setFormValue(this.value);
+ }
}
handleSetName() {