mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
FIX: Ensure DButton uses the correct target for string actions (#19126)
Our `triggerAction` backwards-compatibility was firing the action on `parentView`. In most cases this worked, but it doesn't match the classic behaviour when the DButton is included inside a 'wrapper' component. In that case, the action should be triggered on the current 'this' context of the template that called the DButton. This commit mimics the Ember Classic Component manager's behaviour. It adds the `createCaller` capability to the custom component manager, and then uses the `callerSelfRef` for dispatching the action.
This commit is contained in:
parent
5573257158
commit
269f65f14c
@ -109,8 +109,8 @@ export default class DButton extends GlimmerComponentWithDeprecatedParentView {
|
||||
|
||||
if (typeof actionVal === "string") {
|
||||
deprecated(...ACTION_AS_STRING_DEPRECATION_ARGS);
|
||||
if (this.parentView?.send) {
|
||||
this.parentView.send(actionVal, actionParam);
|
||||
if (this._target?.send) {
|
||||
this._target.send(actionVal, actionParam);
|
||||
} else {
|
||||
throw new Error(
|
||||
"DButton could not find a target for the action. Use a closure action instead"
|
||||
|
@ -4,16 +4,30 @@ import {
|
||||
setInternalComponentManager,
|
||||
} from "@glimmer/manager";
|
||||
import EmberGlimmerComponentManager from "@glimmer/component/-private/ember-component-manager";
|
||||
import { valueForRef } from "@glimmer/reference";
|
||||
|
||||
class GlimmerComponentWithParentViewManager extends CustomComponentManager {
|
||||
create(owner, componentClass, args, environment, dynamicScope) {
|
||||
create(
|
||||
owner,
|
||||
componentClass,
|
||||
args,
|
||||
environment,
|
||||
dynamicScope,
|
||||
callerSelfRef
|
||||
) {
|
||||
const result = super.create(...arguments);
|
||||
|
||||
result.component.parentView = dynamicScope.view;
|
||||
dynamicScope.view = result.component;
|
||||
|
||||
result.component._target = valueForRef(callerSelfRef);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
getCapabilities() {
|
||||
return { ...super.getCapabilities(), createCaller: true };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5,6 +5,7 @@ import { exists, query } from "discourse/tests/helpers/qunit-helpers";
|
||||
import I18n from "I18n";
|
||||
import { hbs } from "ember-cli-htmlbars";
|
||||
import ClassicComponent from "@ember/component";
|
||||
import { withSilencedDeprecationsAsync } from "discourse-common/lib/deprecated";
|
||||
|
||||
module("Integration | Component | d-button", function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
@ -266,16 +267,48 @@ module("Integration | Component | d-button", function (hooks) {
|
||||
this.legacyActionTriggered();
|
||||
},
|
||||
},
|
||||
layout: hbs`<DButton @action="myLegacyAction" />`,
|
||||
});
|
||||
|
||||
await render(
|
||||
hbs`<this.classicComponent @legacyActionTriggered={{this.legacyActionTriggered}}>
|
||||
<DButton @action="myLegacyAction" />
|
||||
</this.classicComponent>
|
||||
`
|
||||
await withSilencedDeprecationsAsync(
|
||||
"discourse.d-button-action-string",
|
||||
async () => {
|
||||
await render(
|
||||
hbs`<this.classicComponent @legacyActionTriggered={{this.legacyActionTriggered}} />`
|
||||
);
|
||||
|
||||
await click(".btn");
|
||||
}
|
||||
);
|
||||
|
||||
await click(".btn");
|
||||
assert.strictEqual(this.foo, "bar");
|
||||
});
|
||||
|
||||
test("Uses correct target with @action string when component called with block", async function (assert) {
|
||||
this.set("foo", null);
|
||||
this.set("legacyActionTriggered", () => this.set("foo", "bar"));
|
||||
|
||||
this.simpleWrapperComponent = ClassicComponent.extend();
|
||||
|
||||
this.classicComponent = ClassicComponent.extend({
|
||||
actions: {
|
||||
myLegacyAction() {
|
||||
this.legacyActionTriggered();
|
||||
},
|
||||
},
|
||||
layout: hbs`<@simpleWrapperComponent><DButton @action="myLegacyAction" /></@simpleWrapperComponent>`,
|
||||
});
|
||||
|
||||
await withSilencedDeprecationsAsync(
|
||||
"discourse.d-button-action-string",
|
||||
async () => {
|
||||
await render(
|
||||
hbs`<this.classicComponent @legacyActionTriggered={{this.legacyActionTriggered}} @simpleWrapperComponent={{this.simpleWrapperComponent}} />`
|
||||
);
|
||||
|
||||
await click(".btn");
|
||||
}
|
||||
);
|
||||
|
||||
assert.strictEqual(this.foo, "bar");
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user