mirror of
https://github.com/discourse/discourse.git
synced 2025-04-26 02:14:29 +08: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|}}
|
{{#each this._childComponents as |info|}}
|
||||||
{{#in-element info.element insertBefore=null}}
|
{{#in-element info.element insertBefore=null}}
|
||||||
<info.component @data={{info.data}} />
|
<info.component
|
||||||
|
@data={{info.data}}
|
||||||
|
@setWrapperElementAttrs={{info.setWrapperElementAttrs}}
|
||||||
|
/>
|
||||||
{{/in-element}}
|
{{/in-element}}
|
||||||
{{/each}}
|
{{/each}}
|
@ -4,6 +4,8 @@ import { tracked } from "@glimmer/tracking";
|
|||||||
import { assert } from "@ember/debug";
|
import { assert } from "@ember/debug";
|
||||||
import { createWidgetFrom } from "discourse/widgets/widget";
|
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.
|
This class allows you to render arbitrary Glimmer templates inside widgets.
|
||||||
@ -71,8 +73,14 @@ createWidget("my-widget", {
|
|||||||
this.scheduleRerender();
|
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 {
|
export default class RenderGlimmer {
|
||||||
@ -104,6 +112,7 @@ export default class RenderGlimmer {
|
|||||||
const [type, ...classNames] = this.renderInto.split(".");
|
const [type, ...classNames] = this.renderInto.split(".");
|
||||||
this.element = document.createElement(type);
|
this.element = document.createElement(type);
|
||||||
this.element.classList.add(...classNames);
|
this.element.classList.add(...classNames);
|
||||||
|
this.element[INITIAL_CLASSES] = classNames;
|
||||||
}
|
}
|
||||||
this.connectComponent();
|
this.connectComponent();
|
||||||
return this.element;
|
return this.element;
|
||||||
@ -147,11 +156,27 @@ export default class RenderGlimmer {
|
|||||||
element,
|
element,
|
||||||
component,
|
component,
|
||||||
@tracked data: this.data,
|
@tracked data: this.data,
|
||||||
|
setWrapperElementAttrs: (attrs) =>
|
||||||
|
this.updateElementAttrs(element, attrs),
|
||||||
};
|
};
|
||||||
|
|
||||||
this.parentMountWidgetComponent.mountChildComponent(this._componentInfo);
|
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() {
|
get parentMountWidgetComponent() {
|
||||||
return this.widget?._findView() || this._emberView;
|
return this.widget?._findView() || this._emberView;
|
||||||
}
|
}
|
||||||
|
@ -133,6 +133,11 @@ module("Integration | Component | Widget | render-glimmer", function (hooks) {
|
|||||||
"div.my-wrapper",
|
"div.my-wrapper",
|
||||||
hbs`<span class='shim-content'>{{@data.attr1}}</span>`
|
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 () {
|
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("widget:toggle-demo-widget");
|
||||||
this.registry.unregister("component:demo-component");
|
this.registry.unregister("component:demo-component");
|
||||||
deleteFromRegistry("render-glimmer-test-shim");
|
deleteFromRegistry("render-glimmer-test-shim");
|
||||||
|
deleteFromRegistry("render-glimmer-test-wrapper-attrs");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("argument handling", async function (assert) {
|
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").exists();
|
||||||
assert.dom("div.my-wrapper span.shim-content").hasText("val1");
|
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…
x
Reference in New Issue
Block a user