mirror of
https://github.com/discourse/discourse.git
synced 2025-01-19 02:52:44 +08:00
DEV: Ensure RenderGlimmer handles in-place component changes (#17946)
If a widget toggles between displaying two different RenderGlimmer instances, the Widget framework treats them as the same, and so `update()` is called rather than destroy/init. This commit detects this scenario and manually destroys/inits to ensure the correct component is being rendered.
This commit is contained in:
parent
1434fe3021
commit
3e010bc88c
|
@ -70,6 +70,16 @@ export default class RenderGlimmer {
|
|||
}
|
||||
|
||||
update(prev) {
|
||||
if (
|
||||
prev.template.__id !== this.template.__id ||
|
||||
prev.tagName !== this.tagName
|
||||
) {
|
||||
// Totally different component, but the widget framework guessed it was the
|
||||
// same widget. Destroy old component and re-init the new one.
|
||||
prev.destroy();
|
||||
return this.init();
|
||||
}
|
||||
|
||||
this._componentInfo = prev._componentInfo;
|
||||
if (prev.data !== this.data) {
|
||||
this._componentInfo.data = this.data;
|
||||
|
|
|
@ -66,6 +66,41 @@ class DemoComponent extends ClassicComponent {
|
|||
}
|
||||
}
|
||||
|
||||
class ToggleDemoWidget extends Widget {
|
||||
static actionTriggered = false;
|
||||
tagName = "div.my-widget";
|
||||
|
||||
buildKey() {
|
||||
return "abc";
|
||||
}
|
||||
|
||||
defaultState() {
|
||||
return {
|
||||
showOne: true,
|
||||
};
|
||||
}
|
||||
|
||||
html(attrs, state) {
|
||||
const output = [
|
||||
this.attach("button", {
|
||||
label: "toggle",
|
||||
className: "toggleButton",
|
||||
action: "toggleComponent",
|
||||
}),
|
||||
];
|
||||
if (state.showOne) {
|
||||
output.push(new RenderGlimmer(this, "div.glimmer-wrapper", hbs`One`, {}));
|
||||
} else {
|
||||
output.push(new RenderGlimmer(this, "div.glimmer-wrapper", hbs`Two`, {}));
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
toggleComponent() {
|
||||
this.state.showOne = !this.state.showOne;
|
||||
}
|
||||
}
|
||||
|
||||
module("Integration | Component | Widget | render-glimmer", function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
|
@ -73,11 +108,13 @@ module("Integration | Component | Widget | render-glimmer", function (hooks) {
|
|||
DemoComponent.eventLog = [];
|
||||
DemoWidget.actionTriggered = false;
|
||||
this.registry.register("widget:demo-widget", DemoWidget);
|
||||
this.registry.register("widget:toggle-demo-widget", ToggleDemoWidget);
|
||||
this.registry.register("component:demo-component", DemoComponent);
|
||||
});
|
||||
|
||||
hooks.afterEach(function () {
|
||||
this.registry.unregister("widget:demo-widget");
|
||||
this.registry.unregister("widget:toggle-demo-widget");
|
||||
this.registry.unregister("component:demo-component");
|
||||
});
|
||||
|
||||
|
@ -217,4 +254,13 @@ module("Integration | Component | Widget | render-glimmer", function (hooks) {
|
|||
new RenderGlimmer(this, "div", hbs`<TheCorrectCompiler />`);
|
||||
assert.true(true, "it doesn't raise an error for correct params");
|
||||
});
|
||||
|
||||
test("multiple adjacent components", async function (assert) {
|
||||
await render(hbs`<MountWidget @widget="toggle-demo-widget" />`);
|
||||
assert.strictEqual(query("div.glimmer-wrapper").innerText, "One");
|
||||
await click(".toggleButton");
|
||||
assert.strictEqual(query("div.glimmer-wrapper").innerText, "Two");
|
||||
await click(".toggleButton");
|
||||
assert.strictEqual(query("div.glimmer-wrapper").innerText, "One");
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue
Block a user