DEV: Introduce API for rendering Glimmer inside posts (#20140)
`helper.renderGlimmer` will return an HTML element which can be added to a post's `cooked` Example usage: ``` import { hbs } from "ember-cli-htmlbars"; api.decorateCookedElement((cooked, helper) => { const glimmerElement = helper.renderGlimmer( "div.my-wrapper-class", hbs`<DButton @icon={{@data.param}} @translatedLabel="Hello world from Glimmer Component"/>`, { param: "user-plus" } ); cooked.appendChild(glimmerElement); }, { onlyStream: true, id: "my-id" }); ``` See `widgets/render-glimmer.js` for more detailed usage information.
This commit is contained in:
parent
adbf69c300
commit
ca2b2d034f
|
@ -2,6 +2,7 @@ import Connector from "discourse/widgets/connector";
|
|||
import PostCooked from "discourse/widgets/post-cooked";
|
||||
import RawHtml from "discourse/widgets/raw-html";
|
||||
import { h } from "virtual-dom";
|
||||
import RenderGlimmer from "discourse/widgets/render-glimmer";
|
||||
|
||||
class DecoratorHelper {
|
||||
constructor(widget, attrs, state) {
|
||||
|
@ -106,6 +107,44 @@ class DecoratorHelper {
|
|||
connect(details) {
|
||||
return new Connector(this.widget, details);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an element containing a rendered glimmer template. For full usage instructions,
|
||||
* see `widgets/render-glimmer.js`.
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* ```
|
||||
* import { hbs } from "ember-cli-htmlbars";
|
||||
*
|
||||
* api.decorateCookedElement((cooked, helper) => {
|
||||
* const glimmerElement = helper.renderGlimmer(
|
||||
* "div.my-wrapper-class",
|
||||
* hbs`<DButton @icon={{@data.param}} @translatedLabel="Hello world from Glimmer Component"/>`,
|
||||
* { param: "user-plus" }
|
||||
* );
|
||||
* cooked.appendChild(glimmerElement);
|
||||
* }, { onlyStream: true, id: "my-id" });
|
||||
* ```
|
||||
*
|
||||
*/
|
||||
renderGlimmer(tagName, template, data) {
|
||||
if (!this.widget.postContentsDestroyCallbacks) {
|
||||
throw "renderGlimmer can only be used in the context of a post";
|
||||
}
|
||||
|
||||
const renderGlimmer = new RenderGlimmer(
|
||||
this.widget,
|
||||
tagName,
|
||||
template,
|
||||
data
|
||||
);
|
||||
renderGlimmer.init();
|
||||
this.widget.postContentsDestroyCallbacks.push(
|
||||
renderGlimmer.destroy.bind(renderGlimmer)
|
||||
);
|
||||
return renderGlimmer.element;
|
||||
}
|
||||
}
|
||||
DecoratorHelper.prototype.h = h;
|
||||
|
||||
|
|
|
@ -629,6 +629,14 @@ createWidget("post-contents", {
|
|||
controller.setProperties({ topic, post });
|
||||
});
|
||||
},
|
||||
|
||||
init() {
|
||||
this.postContentsDestroyCallbacks = [];
|
||||
},
|
||||
|
||||
destroy() {
|
||||
this.postContentsDestroyCallbacks.forEach((c) => c());
|
||||
},
|
||||
});
|
||||
|
||||
createWidget("post-notice", {
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
import Component from "@glimmer/component";
|
||||
import { hbs } from "ember-cli-htmlbars";
|
||||
import { setComponentTemplate } from "@ember/component";
|
||||
import { test } from "qunit";
|
||||
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||
import { visit } from "@ember/test-helpers";
|
||||
import { withPluginApi } from "discourse/lib/plugin-api";
|
||||
|
||||
acceptance("Acceptance | decorateCookedElement", function () {
|
||||
test("decorator with renderGlimmer works", async function (assert) {
|
||||
class DemoComponent extends Component {
|
||||
static eventLog = [];
|
||||
constructor() {
|
||||
DemoComponent.eventLog.push("created");
|
||||
return super(...arguments);
|
||||
}
|
||||
willDestroy() {
|
||||
DemoComponent.eventLog.push("willDestroy");
|
||||
}
|
||||
}
|
||||
setComponentTemplate(
|
||||
hbs`<span class='glimmer-component-content'>Hello world</span>`,
|
||||
DemoComponent
|
||||
);
|
||||
|
||||
withPluginApi(0, (api) => {
|
||||
api.decorateCookedElement((cooked, helper) => {
|
||||
if (helper.getModel().post_number !== 1) {
|
||||
return;
|
||||
}
|
||||
cooked.appendChild(
|
||||
helper.renderGlimmer(
|
||||
"div.glimmer-wrapper",
|
||||
hbs`<@data.component />`,
|
||||
{ component: DemoComponent }
|
||||
)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
await visit("/t/internationalization-localization/280");
|
||||
|
||||
assert.dom("div.glimmer-wrapper").exists();
|
||||
assert.dom("span.glimmer-component-content").exists();
|
||||
assert.deepEqual(DemoComponent.eventLog, ["created"]);
|
||||
|
||||
await visit("/");
|
||||
|
||||
assert.deepEqual(DemoComponent.eventLog, ["created", "willDestroy"]);
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue