mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
DEV: Support appending glimmer into existing post elements (#20164)
Previously `helper.renderGlimmer()` would always create a new wrapper element. This is required when using `RenderGlimmer` within widgets, where there is no direct access to DOM elements. However, when using within `decorateCooked`, we have the ability to pass an existing element to `{{#in-element}}` and have the glimmer content appended with no additional wrappers. This commit makes the `renderInto` accept an existing DOM node for this 'append' behavior. The previous 'new wrapper element' behaviour is still used when a string is passed.
This commit is contained in:
parent
082cd13909
commit
d90a31d5b4
@ -1,5 +1,5 @@
|
||||
{{#each this._childComponents as |info|}}
|
||||
{{#in-element info.element}}
|
||||
{{#in-element info.element insertBefore=null}}
|
||||
<info.component @data={{info.data}} />
|
||||
{{/in-element}}
|
||||
{{/each}}
|
@ -118,24 +118,31 @@ class DecoratorHelper {
|
||||
* import { hbs } from "ember-cli-htmlbars";
|
||||
*
|
||||
* api.decorateCookedElement((cooked, helper) => {
|
||||
* // Generate a new element with glimmer rendered inside
|
||||
* 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);
|
||||
*
|
||||
* // Or append to an existing element
|
||||
* helper.renderGlimmer(
|
||||
* cooked.querySelector(".some-container"),
|
||||
* hbs`I will be appended to some-container`
|
||||
* );
|
||||
* }, { onlyStream: true, id: "my-id" });
|
||||
* ```
|
||||
*
|
||||
*/
|
||||
renderGlimmer(tagName, template, data) {
|
||||
renderGlimmer(renderInto, 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,
|
||||
renderInto,
|
||||
template,
|
||||
data
|
||||
);
|
||||
|
@ -78,25 +78,30 @@ export default class RenderGlimmer {
|
||||
/**
|
||||
* Create a RenderGlimmer instance
|
||||
* @param widget - the widget instance which is rendering this content
|
||||
* @param tagName - tagName for the wrapper element (e.g. `div.my-class`)
|
||||
* @param renderInto - a string describing a new wrapper element (e.g. `div.my-class`),
|
||||
* or an existing HTML element to append content into.
|
||||
* @param template - a glimmer template compiled via ember-cli-htmlbars
|
||||
* @param data - will be made available at `@data` in your template
|
||||
*/
|
||||
constructor(widget, tagName, template, data) {
|
||||
constructor(widget, renderInto, template, data) {
|
||||
assert(
|
||||
"`template` should be a template compiled via `ember-cli-htmlbars`",
|
||||
template.name === "factory"
|
||||
);
|
||||
this.tagName = tagName;
|
||||
this.renderInto = renderInto;
|
||||
this.widget = widget;
|
||||
this.template = template;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
init() {
|
||||
const [type, ...classNames] = this.tagName.split(".");
|
||||
this.element = document.createElement(type);
|
||||
this.element.classList.add(...classNames);
|
||||
if (this.renderInto instanceof Element) {
|
||||
this.element = this.renderInto;
|
||||
} else {
|
||||
const [type, ...classNames] = this.renderInto.split(".");
|
||||
this.element = document.createElement(type);
|
||||
this.element.classList.add(...classNames);
|
||||
}
|
||||
this.connectComponent();
|
||||
return this.element;
|
||||
}
|
||||
@ -110,7 +115,7 @@ export default class RenderGlimmer {
|
||||
update(prev) {
|
||||
if (
|
||||
prev.template.__id !== this.template.__id ||
|
||||
prev.tagName !== this.tagName
|
||||
prev.renderInto !== this.renderInto
|
||||
) {
|
||||
// Totally different component, but the widget framework guessed it was the
|
||||
// same widget. Destroy old component and re-init the new one.
|
||||
|
@ -28,6 +28,10 @@ acceptance("Acceptance | decorateCookedElement", function () {
|
||||
if (helper.getModel().post_number !== 1) {
|
||||
return;
|
||||
}
|
||||
cooked.innerHTML =
|
||||
"<div class='existing-wrapper'>Some existing content</div>";
|
||||
|
||||
// Create new wrapper element and append
|
||||
cooked.appendChild(
|
||||
helper.renderGlimmer(
|
||||
"div.glimmer-wrapper",
|
||||
@ -35,6 +39,12 @@ acceptance("Acceptance | decorateCookedElement", function () {
|
||||
{ component: DemoComponent }
|
||||
)
|
||||
);
|
||||
|
||||
// Append to existing element
|
||||
helper.renderGlimmer(
|
||||
cooked.querySelector(".existing-wrapper"),
|
||||
hbs` with more content from glimmer`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@ -42,6 +52,12 @@ acceptance("Acceptance | decorateCookedElement", function () {
|
||||
|
||||
assert.dom("div.glimmer-wrapper").exists();
|
||||
assert.dom("span.glimmer-component-content").exists();
|
||||
|
||||
assert.dom("div.existing-wrapper").exists();
|
||||
assert
|
||||
.dom("div.existing-wrapper")
|
||||
.hasText("Some existing content with more content from glimmer");
|
||||
|
||||
assert.deepEqual(DemoComponent.eventLog, ["created"]);
|
||||
|
||||
await visit("/");
|
||||
|
Loading…
Reference in New Issue
Block a user