FIX: Ensure that custom {{action}} modifier works with actions hash (#18779)
A callback that's provided as a string, such as `{{action "doSomething"}}`, may target the method `doSomething` on the context OR the context's `action` hash (if it exists).
This commit is contained in:
parent
9b1536fb83
commit
952b033165
|
@ -16,7 +16,12 @@ export const actionModifier = modifier(
|
|||
{ on, bubbles, preventDefault, allowedKeys }
|
||||
) => {
|
||||
const handler = (event) => {
|
||||
const fn = typeof callback === "string" ? context[callback] : callback;
|
||||
let fn;
|
||||
if (typeof callback === "string") {
|
||||
fn = context.actions?.[callback] ?? context[callback];
|
||||
} else if (typeof callback === "function") {
|
||||
fn = callback;
|
||||
}
|
||||
if (fn === undefined) {
|
||||
throw new Error(
|
||||
"Unexpected callback for `action` modifier. Please provide either a function or the name of a method on the current context."
|
||||
|
|
|
@ -2,6 +2,7 @@ import { module, test } from "qunit";
|
|||
import { setupRenderingTest } from "ember-qunit";
|
||||
import { click, doubleClick, render } from "@ember/test-helpers";
|
||||
import { hbs } from "ember-cli-htmlbars";
|
||||
import { default as ClassicComponent } from "@ember/component";
|
||||
|
||||
module("Unit | Lib | ember-action-modifer", function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
@ -73,4 +74,110 @@ module("Unit | Lib | ember-action-modifer", function (hooks) {
|
|||
|
||||
assert.strictEqual(this.dblClicked, 0);
|
||||
});
|
||||
|
||||
module("used on a classic component", function () {
|
||||
const ExampleClassicButton = ClassicComponent.extend({
|
||||
tagName: "",
|
||||
onDoSomething: null,
|
||||
|
||||
doSomething() {
|
||||
this.onDoSomething?.("doSomething");
|
||||
},
|
||||
});
|
||||
const ExampleClassicButtonWithActions = ClassicComponent.extend({
|
||||
tagName: "",
|
||||
onDoSomething: null,
|
||||
|
||||
doSomething() {
|
||||
this.onDoSomething?.("doSomething");
|
||||
},
|
||||
|
||||
actions: {
|
||||
doSomething() {
|
||||
this.onDoSomething?.("actions.doSomething");
|
||||
},
|
||||
},
|
||||
});
|
||||
const exampleClassicButtonTemplate = hbs`
|
||||
<a
|
||||
href
|
||||
class="btn btn-default no-text mobile-gif-insert"
|
||||
aria-label={{i18n "gif.composer_title"}}
|
||||
{{action "doSomething"}}
|
||||
>
|
||||
{{d-icon "discourse-gifs-gif"}}
|
||||
</a>
|
||||
`;
|
||||
|
||||
hooks.beforeEach(function () {
|
||||
this.owner.register(
|
||||
"component:example-classic-button",
|
||||
ExampleClassicButton
|
||||
);
|
||||
this.owner.register(
|
||||
"template:components/example-classic-button",
|
||||
exampleClassicButtonTemplate
|
||||
);
|
||||
this.owner.register(
|
||||
"component:example-classic-button-with-actions",
|
||||
ExampleClassicButtonWithActions
|
||||
);
|
||||
this.owner.register(
|
||||
"template:components/example-classic-button-with-actions",
|
||||
exampleClassicButtonTemplate
|
||||
);
|
||||
});
|
||||
|
||||
test("it can target a listener on the context", async function (assert) {
|
||||
let i = 0;
|
||||
|
||||
this.setProperties({
|
||||
onOneClick: (source) => {
|
||||
assert.strictEqual(
|
||||
source,
|
||||
"doSomething",
|
||||
"handler on context is invoked"
|
||||
);
|
||||
this.set("oneClicked", i++);
|
||||
},
|
||||
oneClicked: undefined,
|
||||
});
|
||||
|
||||
await render(hbs`
|
||||
<ExampleClassicButton @onDoSomething={{this.onOneClick}} />
|
||||
`);
|
||||
|
||||
assert.strictEqual(this.oneClicked, undefined);
|
||||
|
||||
await click("a.btn");
|
||||
|
||||
assert.strictEqual(this.oneClicked, 0);
|
||||
});
|
||||
|
||||
test("it can target a listener on the actions hash", async function (assert) {
|
||||
let i = 0;
|
||||
|
||||
this.setProperties({
|
||||
onOneClick: (source) => {
|
||||
assert.strictEqual(
|
||||
source,
|
||||
"actions.doSomething",
|
||||
"handler on actions hash is given precedence"
|
||||
);
|
||||
this.set("oneClicked", i++);
|
||||
},
|
||||
oneClicked: undefined,
|
||||
});
|
||||
|
||||
await render(hbs`
|
||||
<ExampleClassicButtonWithActions @onDoSomething={{this.onOneClick}} />
|
||||
`);
|
||||
|
||||
assert.strictEqual(this.oneClicked, undefined);
|
||||
|
||||
await click("a.btn");
|
||||
|
||||
assert.strictEqual(this.oneClicked, 0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue