DEV: Allow registering a widget shim which renders using hbs (#20177)
This is an alternative way to use `RenderGlimmer` which can be more ergonomic for iterative updates of a codebase. For documentation, see `widgets/render-glimmer.js`
This commit is contained in:
parent
2f8ad17aed
commit
95999c80ce
|
@ -2,6 +2,7 @@ import templateOnly from "@ember/component/template-only";
|
||||||
import { setComponentTemplate } from "@ember/component";
|
import { setComponentTemplate } from "@ember/component";
|
||||||
import { tracked } from "@glimmer/tracking";
|
import { tracked } from "@glimmer/tracking";
|
||||||
import { assert } from "@ember/debug";
|
import { assert } from "@ember/debug";
|
||||||
|
import { createWidgetFrom } from "discourse/widgets/widget";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
|
@ -89,7 +90,9 @@ export default class RenderGlimmer {
|
||||||
template.name === "factory"
|
template.name === "factory"
|
||||||
);
|
);
|
||||||
this.renderInto = renderInto;
|
this.renderInto = renderInto;
|
||||||
|
if (widget) {
|
||||||
this.widget = widget;
|
this.widget = widget;
|
||||||
|
}
|
||||||
this.template = template;
|
this.template = template;
|
||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
|
@ -108,7 +111,9 @@ export default class RenderGlimmer {
|
||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
if (this._componentInfo) {
|
if (this._componentInfo) {
|
||||||
this.widget._findView().unmountChildComponent(this._componentInfo);
|
this.parentMountWidgetComponent.unmountChildComponent(
|
||||||
|
this._componentInfo
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,7 +137,7 @@ export default class RenderGlimmer {
|
||||||
}
|
}
|
||||||
|
|
||||||
connectComponent() {
|
connectComponent() {
|
||||||
const { element, template, widget } = this;
|
const { element, template } = this;
|
||||||
|
|
||||||
const component = templateOnly();
|
const component = templateOnly();
|
||||||
component.name = "Widgets/RenderGlimmer";
|
component.name = "Widgets/RenderGlimmer";
|
||||||
|
@ -143,9 +148,39 @@ export default class RenderGlimmer {
|
||||||
component,
|
component,
|
||||||
@tracked data: this.data,
|
@tracked data: this.data,
|
||||||
};
|
};
|
||||||
const parentMountWidgetComponent = widget._findView();
|
|
||||||
parentMountWidgetComponent.mountChildComponent(this._componentInfo);
|
this.parentMountWidgetComponent.mountChildComponent(this._componentInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
get parentMountWidgetComponent() {
|
||||||
|
return this.widget?._findView() || this._emberView;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderGlimmer.prototype.type = "Widget";
|
RenderGlimmer.prototype.type = "Widget";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define a widget shim which renders a Glimmer template. Designed for incrementally migrating
|
||||||
|
* a widget-based UI to Glimmer. Widget attrs will be made available to your template at `@data`.
|
||||||
|
* For more details, see documentation for the RenderGlimmer class.
|
||||||
|
* @param name - the widget's name (which can then be used in `.attach` elsewhere)
|
||||||
|
* @param tagName - a string describing a new wrapper element (e.g. `div.my-class`)
|
||||||
|
* @param template - a glimmer template compiled via ember-cli-htmlbars
|
||||||
|
*/
|
||||||
|
export function registerWidgetShim(name, tagName, template) {
|
||||||
|
const RenderGlimmerShim = class MyClass extends RenderGlimmer {
|
||||||
|
constructor(attrs) {
|
||||||
|
super(null, tagName, template, attrs);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
get widget() {
|
||||||
|
return this.parentWidget;
|
||||||
|
}
|
||||||
|
|
||||||
|
didRenderWidget() {}
|
||||||
|
willRerenderWidget() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
createWidgetFrom(RenderGlimmerShim, name, {});
|
||||||
|
}
|
||||||
|
|
|
@ -30,6 +30,10 @@ export function queryRegistry(name) {
|
||||||
return _registry[name];
|
return _registry[name];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function deleteFromRegistry(name) {
|
||||||
|
return delete _registry[name];
|
||||||
|
}
|
||||||
|
|
||||||
const _decorators = {};
|
const _decorators = {};
|
||||||
|
|
||||||
export function decorateWidget(widgetName, cb) {
|
export function decorateWidget(widgetName, cb) {
|
||||||
|
|
|
@ -4,9 +4,11 @@ import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
||||||
import { click, fillIn, render } from "@ember/test-helpers";
|
import { click, fillIn, render } from "@ember/test-helpers";
|
||||||
import { hbs } from "ember-cli-htmlbars";
|
import { hbs } from "ember-cli-htmlbars";
|
||||||
import widgetHbs from "discourse/widgets/hbs-compiler";
|
import widgetHbs from "discourse/widgets/hbs-compiler";
|
||||||
import Widget from "discourse/widgets/widget";
|
import Widget, { deleteFromRegistry } from "discourse/widgets/widget";
|
||||||
import ClassicComponent from "@ember/component";
|
import ClassicComponent from "@ember/component";
|
||||||
import RenderGlimmer from "discourse/widgets/render-glimmer";
|
import RenderGlimmer, {
|
||||||
|
registerWidgetShim,
|
||||||
|
} from "discourse/widgets/render-glimmer";
|
||||||
import { bind } from "discourse-common/utils/decorators";
|
import { bind } from "discourse-common/utils/decorators";
|
||||||
|
|
||||||
class DemoWidget extends Widget {
|
class DemoWidget extends Widget {
|
||||||
|
@ -126,12 +128,18 @@ module("Integration | Component | Widget | render-glimmer", function (hooks) {
|
||||||
this.registry.register("widget:demo-widget", DemoWidget);
|
this.registry.register("widget:demo-widget", DemoWidget);
|
||||||
this.registry.register("widget:toggle-demo-widget", ToggleDemoWidget);
|
this.registry.register("widget:toggle-demo-widget", ToggleDemoWidget);
|
||||||
this.registry.register("component:demo-component", DemoComponent);
|
this.registry.register("component:demo-component", DemoComponent);
|
||||||
|
registerWidgetShim(
|
||||||
|
"render-glimmer-test-shim",
|
||||||
|
"div.my-wrapper",
|
||||||
|
hbs`<span class='shim-content'>{{@data.attr1}}</span>`
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
hooks.afterEach(function () {
|
hooks.afterEach(function () {
|
||||||
this.registry.unregister("widget:demo-widget");
|
this.registry.unregister("widget:demo-widget");
|
||||||
this.registry.unregister("widget:toggle-demo-widget");
|
this.registry.unregister("widget:toggle-demo-widget");
|
||||||
this.registry.unregister("component:demo-component");
|
this.registry.unregister("component:demo-component");
|
||||||
|
deleteFromRegistry("render-glimmer-test-shim");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("argument handling", async function (assert) {
|
test("argument handling", async function (assert) {
|
||||||
|
@ -310,4 +318,13 @@ module("Integration | Component | Widget | render-glimmer", function (hooks) {
|
||||||
await click(".toggleButton");
|
await click(".toggleButton");
|
||||||
assert.strictEqual(query("div.glimmer-wrapper").innerText, "One");
|
assert.strictEqual(query("div.glimmer-wrapper").innerText, "One");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("registerWidgetShim can register a fake widget", async function (assert) {
|
||||||
|
await render(
|
||||||
|
hbs`<MountWidget @widget="render-glimmer-test-shim" @args={{hash attr1="val1"}} />`
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.dom("div.my-wrapper span.shim-content").exists();
|
||||||
|
assert.dom("div.my-wrapper span.shim-content").hasText("val1");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue