FIX: email fields lose focus in legacy category settings (#37669)

When `enable_simplified_category_creation` is disabled, the email fields
in category settings lose focus after every keystroke, making it
impossible to type an email address.

The legacy category editor wraps all tabs in a FormKit `<Form>`
component. The Form wrapper uses `{{#each (array @data)}}` which
destroys and recreates the entire component tree when `@data` changes
identity. Since the controller's `formData` getter returns a new object
(via `getProperties`) every time a model property changes, any two-way
binding mutation — including every keystroke in a `<TextField>` —
triggers a full teardown and rebuild of all form elements, destroying
the focused input.

This commit converts the email section inputs (`email_in`,
`email_in_allow_strangers`, `mailinglist_mirror`) from two-way model
bindings to use FormKit's data layer (`form.set` / `transientData`).
Edits to these fields no longer mutate the model, so `formData` isn't
invalidated and the form is not recreated.

This commit also passes `form` to the `category-email-in` and
`category-custom-settings` plugin outlets on the legacy page, matching
what the simplified page already does, so that plugins can adopt FormKit
as well.

https://meta.discourse.org/t/395609
This commit is contained in:
Régis Hanol
2026-02-12 10:47:49 +11:00
committed by GitHub
parent 84706bcef7
commit c0f38c1a57
@@ -171,6 +171,11 @@ export default class EditCategorySettings extends buildCategoryPanel(
this.set("category.moderating_group_ids", groupIds);
}
@action
onFormCheckboxChange(field, event) {
this.form.set(field, event.target.checked);
}
<template>
<section>
{{#if this.showPositionInput}}
@@ -520,19 +525,24 @@ export default class EditCategorySettings extends buildCategoryPanel(
{{icon "envelope"}}
{{i18n "category.email_in"}}
</label>
<TextField
@id="category-email-in"
@value={{this.category.email_in}}
<input
type="text"
id="category-email-in"
class="email-in"
value={{this.transientData.email_in}}
{{on "input" (withEventValue (fn this.form.set "email_in"))}}
/>
</section>
<section class="field email-in-allow-strangers">
<label class="checkbox-label">
<Input
@type="checkbox"
@checked={{this.category.email_in_allow_strangers}}
<input
type="checkbox"
checked={{this.transientData.email_in_allow_strangers}}
{{on
"change"
(fn this.onFormCheckboxChange "email_in_allow_strangers")
}}
/>
{{i18n "category.email_in_allow_strangers"}}
</label>
@@ -540,9 +550,13 @@ export default class EditCategorySettings extends buildCategoryPanel(
<section class="field mailinglist-mirror">
<label class="checkbox-label">
<Input
@type="checkbox"
@checked={{this.category.mailinglist_mirror}}
<input
type="checkbox"
checked={{this.transientData.mailinglist_mirror}}
{{on
"change"
(fn this.onFormCheckboxChange "mailinglist_mirror")
}}
/>
{{i18n "category.mailinglist_mirror"}}
</label>
@@ -552,7 +566,7 @@ export default class EditCategorySettings extends buildCategoryPanel(
<PluginOutlet
@name="category-email-in"
@connectorTagName="div"
@outletArgs={{lazyHash category=this.category}}
@outletArgs={{lazyHash category=this.category form=this.form}}
/>
</span>
{{/if}}
@@ -574,7 +588,7 @@ export default class EditCategorySettings extends buildCategoryPanel(
<section>
<PluginOutlet
@name="category-custom-settings"
@outletArgs={{lazyHash category=this.category}}
@outletArgs={{lazyHash category=this.category form=this.form}}
/>
</section>
</template>