DEV: Introduce a helper for handling events (#25433)

Instead of

```hbs
{{on "input" (action this.foo value="target.value")}}
{{on "input" (action (mut this.bar) value="target.value")}}
```

you can use:

```hbs
{{on "input" (with-event-value this.foo)}}
{{on "input" (with-event-value (fn (mut this.bar)))}}
```

or in gjs:

```gjs
import { fn } from "@ember/helper";
import { on } from "@ember/modifier";
import withEventValue from "discourse/helpers/with-event-value";
…
{{on "input" (withEventValue (fn (mut this.bar)))}}
```
This commit is contained in:
Jarek Radosz 2024-02-28 14:00:53 +01:00 committed by GitHub
parent 0e17ff8d09
commit 36a9b5d0fa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 42 additions and 62 deletions

View File

@ -1,5 +1,5 @@
<input <input
{{on "input" (action (mut this.value) value="target.value")}} {{on "input" (with-event-value (fn (mut this.value)))}}
type="number" type="number"
value={{this.value}} value={{this.value}}
min={{if this.setting.min this.setting.min null}} min={{if this.setting.min this.setting.min null}}

View File

@ -6,7 +6,7 @@
class="filter-reports-input" class="filter-reports-input"
placeholder={{i18n "admin.dashboard.filter_reports"}} placeholder={{i18n "admin.dashboard.filter_reports"}}
autofocus={{true}} autofocus={{true}}
{{on "input" (action "filterReports" value="target.value")}} {{on "input" (with-event-value this.filterReports)}}
/> />
</div> </div>

View File

@ -5,10 +5,7 @@
{{i18n "category.position"}} {{i18n "category.position"}}
</label> </label>
<input <input
{{on {{on "input" (with-event-value (fn (mut this.category.position)))}}
"input"
(action (mut this.category.position) value="target.value")
}}
value={{this.category.position}} value={{this.category.position}}
type="number" type="number"
min="0" min="0"
@ -42,7 +39,7 @@
<input <input
{{on {{on
"input" "input"
(action (mut this.category.num_featured_topics) value="target.value") (with-event-value (fn (mut this.category.num_featured_topics)))
}} }}
value={{this.category.num_featured_topics}} value={{this.category.num_featured_topics}}
type="number" type="number"
@ -197,9 +194,8 @@
<input <input
{{on {{on
"input" "input"
(action (with-event-value
(mut this.category.category_setting.num_auto_bump_daily) (fn (mut this.category.category_setting.num_auto_bump_daily))
value="target.value"
) )
}} }}
value={{this.category.category_setting.num_auto_bump_daily}} value={{this.category.category_setting.num_auto_bump_daily}}
@ -216,9 +212,8 @@
<input <input
{{on {{on
"input" "input"
(action (with-event-value
(mut this.category.category_setting.auto_bump_cooldown_days) (fn (mut this.category.category_setting.auto_bump_cooldown_days))
value="target.value"
) )
}} }}
value={{this.category.category_setting.auto_bump_cooldown_days}} value={{this.category.category_setting.auto_bump_cooldown_days}}

View File

@ -9,7 +9,7 @@
name="name" name="name"
placeholder={{i18n "admin.emoji.name"}} placeholder={{i18n "admin.emoji.name"}}
@value={{readonly this.name}} @value={{readonly this.name}}
{{on "input" (action (mut this.name) value="target.value")}} {{on "input" (with-event-value (fn (mut this.name)))}}
/> />
</div> </div>
</div> </div>

View File

@ -33,7 +33,7 @@
class="time-input" class="time-input"
@value={{this._time}} @value={{this._time}}
disabled={{this.timeInputDisabled}} disabled={{this.timeInputDisabled}}
{{on "input" (action "onChangeTime" value="target.value")}} {{on "input" (with-event-value this.onChangeTime)}}
/> />
</div> </div>
{{/if}} {{/if}}

View File

@ -22,10 +22,7 @@
<td> <td>
<div class="reorder-categories-actions"> <div class="reorder-categories-actions">
<input <input
{{on {{on "change" (with-event-value (fn this.change entry))}}
"change"
(action (fn this.change entry) value="target.value")
}}
value={{entry.position}} value={{entry.position}}
type="number" type="number"
min="0" min="0"

View File

@ -21,7 +21,7 @@
id="section-name" id="section-name"
{{on {{on
"input" "input"
(action (mut this.transformedModel.title) value="target.value") (with-event-value (fn (mut this.transformedModel.title)))
}} }}
/> />

View File

@ -10,7 +10,7 @@ export default TextField.extend({
init() { init() {
this._super(...arguments); this._super(...arguments);
deprecated( deprecated(
`NumberField component is deprecated. Use native <input> elements instead.\ne.g. <input {{on "input" (action (mut this.value) value="target.value")}} type="number" value={{this.value}} />`, `NumberField component is deprecated. Use native <input> elements instead.\ne.g. <input {{on "input" (with-event-value (fn (mut this.value)))}} type="number" value={{this.value}} />`,
{ {
id: "discourse.number-field", id: "discourse.number-field",
since: "3.2.0.beta5", since: "3.2.0.beta5",

View File

@ -246,10 +246,7 @@
id="search-min-post-count" id="search-min-post-count"
placeholder={{i18n "search.advanced.post.min.placeholder"}} placeholder={{i18n "search.advanced.post.min.placeholder"}}
aria-label={{i18n "search.advanced.post.min.aria_label"}} aria-label={{i18n "search.advanced.post.min.aria_label"}}
{{on {{on "input" (with-event-value this.onChangeSearchTermMinPostCount)}}
"input"
(action "onChangeSearchTermMinPostCount" value="target.value")
}}
/> />
{{d-icon "arrows-alt-h"}} {{d-icon "arrows-alt-h"}}
<Input <Input
@ -259,10 +256,7 @@
id="search-max-post-count" id="search-max-post-count"
placeholder={{i18n "search.advanced.post.max.placeholder"}} placeholder={{i18n "search.advanced.post.max.placeholder"}}
aria-label={{i18n "search.advanced.post.max.aria_label"}} aria-label={{i18n "search.advanced.post.max.aria_label"}}
{{on {{on "input" (with-event-value this.onChangeSearchTermMaxPostCount)}}
"input"
(action "onChangeSearchTermMaxPostCount" value="target.value")
}}
/> />
</div> </div>
</div> </div>
@ -278,10 +272,7 @@
id="search-min-views" id="search-min-views"
placeholder={{i18n "search.advanced.min_views.placeholder"}} placeholder={{i18n "search.advanced.min_views.placeholder"}}
aria-label={{i18n "search.advanced.min_views.aria_label"}} aria-label={{i18n "search.advanced.min_views.aria_label"}}
{{on {{on "input" (with-event-value this.onChangeSearchTermMinViews)}}
"input"
(action "onChangeSearchTermMinViews" value="target.value")
}}
/> />
{{d-icon "arrows-alt-h"}} {{d-icon "arrows-alt-h"}}
<Input <Input
@ -291,10 +282,7 @@
id="search-max-views" id="search-max-views"
placeholder={{i18n "search.advanced.max_views.placeholder"}} placeholder={{i18n "search.advanced.max_views.placeholder"}}
aria-label={{i18n "search.advanced.max_views.aria_label"}} aria-label={{i18n "search.advanced.max_views.aria_label"}}
{{on {{on "input" (with-event-value this.onChangeSearchTermMaxViews)}}
"input"
(action "onChangeSearchTermMaxViews" value="target.value")
}}
/> />
</div> </div>
</div> </div>

View File

@ -47,7 +47,7 @@
@value={{@link.name}} @value={{@link.name}}
class={{@link.nameCssClass}} class={{@link.nameCssClass}}
ariaLabel={{i18n "sidebar.sections.custom.links.name.label"}} ariaLabel={{i18n "sidebar.sections.custom.links.name.label"}}
{{on "input" (action (mut @link.name) value="target.value")}} {{on "input" (with-event-value (fn (mut @link.name)))}}
/> />
{{#if @link.invalidNameMessage}} {{#if @link.invalidNameMessage}}
<div class="name warning"> <div class="name warning">
@ -62,7 +62,7 @@
@value={{@link.value}} @value={{@link.value}}
class={{@link.valueCssClass}} class={{@link.valueCssClass}}
ariaLabel={{i18n "sidebar.sections.custom.links.value.label"}} ariaLabel={{i18n "sidebar.sections.custom.links.value.label"}}
{{on "input" (action (mut @link.value) value="target.value")}} {{on "input" (with-event-value (fn (mut @link.value)))}}
/> />
{{#if @link.invalidValueMessage}} {{#if @link.invalidValueMessage}}
<div class="value warning"> <div class="value warning">

View File

@ -7,7 +7,7 @@
@id="edit-name" @id="edit-name"
@value={{readonly this.tagInfo.name}} @value={{readonly this.tagInfo.name}}
@maxlength={{this.siteSettings.max_tag_length}} @maxlength={{this.siteSettings.max_tag_length}}
@input={{action (mut this.newTagName) value="target.value"}} @input={{with-event-value (fn (mut this.newTagName))}}
@autofocus="true" @autofocus="true"
/> />
@ -16,10 +16,7 @@
@value={{readonly this.tagInfo.descriptionWithNewLines}} @value={{readonly this.tagInfo.descriptionWithNewLines}}
placeholder={{i18n "tagging.description"}} placeholder={{i18n "tagging.description"}}
maxlength={{1000}} maxlength={{1000}}
{{on {{on "input" (with-event-value (fn (mut this.newTagDescription)))}}
"input"
(action (mut this.newTagDescription) value="target.value")
}}
autofocus="true" autofocus="true"
/> />

View File

@ -0,0 +1,7 @@
import { get } from "@ember/object";
export default function withEventValue(mutFn) {
return function (event) {
return mutFn(get(event, "target.value"));
};
}

View File

@ -22,7 +22,7 @@
@value={{readonly this.filter}} @value={{readonly this.filter}}
placeholder={{i18n "groups.index.all"}} placeholder={{i18n "groups.index.all"}}
class="groups-header-filters-name no-blur" class="groups-header-filters-name no-blur"
{{on "input" (action "onFilterChanged" value="target.value")}} {{on "input" (with-event-value this.onFilterChanged)}}
@type="search" @type="search"
aria-description={{i18n "groups.index.search_results"}} aria-description={{i18n "groups.index.search_results"}}
/> />

View File

@ -41,10 +41,7 @@
@value={{readonly this.nameInput}} @value={{readonly this.nameInput}}
placeholder={{i18n "directory.filter_name"}} placeholder={{i18n "directory.filter_name"}}
class="filter-name no-blur" class="filter-name no-blur"
{{on {{on "input" (with-event-value this.onUsernameFilterChanged)}}
"input"
(action "onUsernameFilterChanged" value="target.value")
}}
/> />
{{#if this.showGroupFilter}} {{#if this.showGroupFilter}}
<ComboBox <ComboBox

View File

@ -20,9 +20,14 @@ module("Integration | Component | char-counter", function (hooks) {
test("updating value updates counter", async function (assert) { test("updating value updates counter", async function (assert) {
this.max = 50; this.max = 50;
await render( await render(hbs`
hbs`<CharCounter @value={{this.charCounterContent}} @max={{this.max}}><textarea {{on "input" (action (mut this.charCounterContent) value="target.value")}}></textarea></CharCounter>` <CharCounter
); @value={{this.charCounterContent}}
@max={{this.max}}
>
<textarea {{on "input" (with-event-value (fn (mut this.charCounterContent)))}}></textarea>
</CharCounter>
`);
assert assert
.dom(this.element) .dom(this.element)

View File

@ -25,7 +25,7 @@
) )
}} }}
@value={{this.chatEmojiPickerManager.picker.initialFilter}} @value={{this.chatEmojiPickerManager.picker.initialFilter}}
@filterAction={{action this.didInputFilter value="target.value"}} @filterAction={{with-event-value this.didInputFilter}}
@icons={{hash left="search"}} @icons={{hash left="search"}}
@containerClass="chat-emoji-picker__filter" @containerClass="chat-emoji-picker__filter"
autofocus={{true}} autofocus={{true}}

View File

@ -17,7 +17,7 @@
class="chat-modal-create-channel__input" class="chat-modal-create-channel__input"
@type="text" @type="text"
@value={{this.name}} @value={{this.name}}
{{on "input" (action this.onNameChange value="target.value")}} {{on "input" (with-event-value this.onNameChange)}}
/> />
</div> </div>

View File

@ -14,10 +14,7 @@
@max={{this.descriptionMaxLength}} @max={{this.descriptionMaxLength}}
> >
<textarea <textarea
{{on {{on "input" (with-event-value this.onChangeChatChannelDescription)}}
"input"
(action this.onChangeChatChannelDescription value="target.value")
}}
class="chat-modal-edit-channel-description__description-input" class="chat-modal-edit-channel-description__description-input"
placeholder={{i18n placeholder={{i18n
"chat.channel_edit_description_modal.input_placeholder" "chat.channel_edit_description_modal.input_placeholder"

View File

@ -1,10 +1,7 @@
<StyleguideExample @title="<CharCounter>"> <StyleguideExample @title="<CharCounter>">
<CharCounter @max="50" @value={{@dummy.charCounterContent}}> <CharCounter @max="50" @value={{@dummy.charCounterContent}}>
<textarea <textarea
{{on {{on "input" (with-event-value (fn (mut @dummy.charCounterContent)))}}
"input"
(action (mut @dummy.charCounterContent) value="target.value")
}}
class="styleguide--char-counter" class="styleguide--char-counter"
></textarea> ></textarea>
</CharCounter> </CharCounter>