mirror of
https://github.com/discourse/discourse.git
synced 2024-11-30 04:34:13 -06:00
DEV: Introduce dynamic wrapper attributes in RenderGlimmer (#22991)
This commit is contained in:
parent
3e44f04ff5
commit
7f2e42c826
@ -1,5 +1,8 @@
|
||||
{{#each this._childComponents as |info|}}
|
||||
{{#in-element info.element insertBefore=null}}
|
||||
<info.component @data={{info.data}} />
|
||||
<info.component
|
||||
@data={{info.data}}
|
||||
@setWrapperElementAttrs={{info.setWrapperElementAttrs}}
|
||||
/>
|
||||
{{/in-element}}
|
||||
{{/each}}
|
@ -4,6 +4,8 @@ import { tracked } from "@glimmer/tracking";
|
||||
import { assert } from "@ember/debug";
|
||||
import { createWidgetFrom } from "discourse/widgets/widget";
|
||||
|
||||
const INITIAL_CLASSES = Symbol("RENDER_GLIMMER_INITIAL_CLASSES");
|
||||
|
||||
/*
|
||||
|
||||
This class allows you to render arbitrary Glimmer templates inside widgets.
|
||||
@ -71,8 +73,14 @@ createWidget("my-widget", {
|
||||
this.scheduleRerender();
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
To dynamically control the attributes of the wrapper element, a helper function is provided as an argument to your hbs template.
|
||||
To use this via a template, you can do something like this:
|
||||
```
|
||||
hbs`{{@setWrapperElementAttrs class="some class value" title="title value"}}`
|
||||
```
|
||||
If you prefer, you can pass this function down into your own components, and call it from there. Invoked as a helper, this can
|
||||
be passed (auto-)tracked values, and will update the wrapper element attributes whenever the inputs.
|
||||
*/
|
||||
|
||||
export default class RenderGlimmer {
|
||||
@ -104,6 +112,7 @@ export default class RenderGlimmer {
|
||||
const [type, ...classNames] = this.renderInto.split(".");
|
||||
this.element = document.createElement(type);
|
||||
this.element.classList.add(...classNames);
|
||||
this.element[INITIAL_CLASSES] = classNames;
|
||||
}
|
||||
this.connectComponent();
|
||||
return this.element;
|
||||
@ -147,11 +156,27 @@ export default class RenderGlimmer {
|
||||
element,
|
||||
component,
|
||||
@tracked data: this.data,
|
||||
setWrapperElementAttrs: (attrs) =>
|
||||
this.updateElementAttrs(element, attrs),
|
||||
};
|
||||
|
||||
this.parentMountWidgetComponent.mountChildComponent(this._componentInfo);
|
||||
}
|
||||
|
||||
updateElementAttrs(element, attrs) {
|
||||
for (let [key, value] of Object.entries(attrs)) {
|
||||
if (key === "class") {
|
||||
value = [element[INITIAL_CLASSES], value].filter(Boolean).join(" ");
|
||||
}
|
||||
|
||||
if ([null, undefined].includes(value)) {
|
||||
element.removeAttribute(key);
|
||||
} else {
|
||||
element.setAttribute(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get parentMountWidgetComponent() {
|
||||
return this.widget?._findView() || this._emberView;
|
||||
}
|
||||
|
@ -133,6 +133,11 @@ module("Integration | Component | Widget | render-glimmer", function (hooks) {
|
||||
"div.my-wrapper",
|
||||
hbs`<span class='shim-content'>{{@data.attr1}}</span>`
|
||||
);
|
||||
registerWidgetShim(
|
||||
"render-glimmer-test-wrapper-attrs",
|
||||
"div.initial-wrapper-class",
|
||||
hbs`{{@setWrapperElementAttrs class=(concat-class "static-extra-class" @data.extraClass) data-some-attr=@data.dataAttrValue}}`
|
||||
);
|
||||
});
|
||||
|
||||
hooks.afterEach(function () {
|
||||
@ -140,6 +145,7 @@ module("Integration | Component | Widget | render-glimmer", function (hooks) {
|
||||
this.registry.unregister("widget:toggle-demo-widget");
|
||||
this.registry.unregister("component:demo-component");
|
||||
deleteFromRegistry("render-glimmer-test-shim");
|
||||
deleteFromRegistry("render-glimmer-test-wrapper-attrs");
|
||||
});
|
||||
|
||||
test("argument handling", async function (assert) {
|
||||
@ -315,4 +321,31 @@ module("Integration | Component | Widget | render-glimmer", function (hooks) {
|
||||
assert.dom("div.my-wrapper span.shim-content").exists();
|
||||
assert.dom("div.my-wrapper span.shim-content").hasText("val1");
|
||||
});
|
||||
|
||||
test("setWrapperElementAttrs API", async function (assert) {
|
||||
await render(
|
||||
hbs`<MountWidget @widget="render-glimmer-test-wrapper-attrs" @args={{hash extraClass=this.extraClass dataAttrValue=this.dataAttrValue}} />`
|
||||
);
|
||||
|
||||
assert.dom("div.initial-wrapper-class").exists();
|
||||
assert
|
||||
.dom("div.initial-wrapper-class")
|
||||
.hasAttribute("class", "initial-wrapper-class static-extra-class");
|
||||
assert
|
||||
.dom("div.initial-wrapper-class")
|
||||
.doesNotHaveAttribute("data-some-attr");
|
||||
|
||||
this.set("extraClass", "dynamic-extra-class");
|
||||
this.set("dataAttrValue", "hello world");
|
||||
|
||||
assert
|
||||
.dom("div.initial-wrapper-class")
|
||||
.hasAttribute(
|
||||
"class",
|
||||
"initial-wrapper-class static-extra-class dynamic-extra-class"
|
||||
);
|
||||
assert
|
||||
.dom("div.initial-wrapper-class")
|
||||
.hasAttribute("data-some-attr", "hello world");
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user