From abd2b42307270a314bef6ac1cd49af6e0ae174dc Mon Sep 17 00:00:00 2001
From: Samuel Degueldre
Date: Mon, 9 Jan 2023 10:50:57 +0100
Subject: [PATCH] [IMP] slots: make defaultContent of slot available to slot as
`zero`
In some cases, it is useful for a slot to be able to keep the default
content of the slot it is supposed to replace and simply add extra
content instead of simply replacing it entirely. This commit makes the
default content of a slot available in the context as `zero` similar to
how t-call can access the content that was inside the t-call.
---
src/runtime/template_helpers.ts | 7 ++++
.../__snapshots__/slots.test.ts.snap | 36 +++++++++++++++++++
tests/components/slots.test.ts | 13 +++++++
3 files changed, 56 insertions(+)
diff --git a/src/runtime/template_helpers.ts b/src/runtime/template_helpers.ts
index 82a68e1a..600b9ab3 100644
--- a/src/runtime/template_helpers.ts
+++ b/src/runtime/template_helpers.ts
@@ -29,6 +29,13 @@ function callSlot(
const slots = ctx.props.slots || {};
const { __render, __ctx, __scope } = slots[name] || {};
const slotScope = ObjectCreate(__ctx || {});
+ if (defaultContent) {
+ Object.defineProperty(slotScope, helpers.zero, {
+ get() {
+ return defaultContent(ctx, parent, key);
+ },
+ });
+ }
if (__scope) {
slotScope[__scope] = extra;
}
diff --git a/tests/components/__snapshots__/slots.test.ts.snap b/tests/components/__snapshots__/slots.test.ts.snap
index 4eab0079..0e93fa1e 100644
--- a/tests/components/__snapshots__/slots.test.ts.snap
+++ b/tests/components/__snapshots__/slots.test.ts.snap
@@ -349,6 +349,42 @@ exports[`slots content is the default slot 2`] = `
}"
`;
+exports[`slots default content is available as 0 1`] = `
+"function anonymous(app, bdom, helpers
+) {
+ let { text, createBlock, list, multi, html, toggler, comment } = bdom;
+ let { zero, markRaw } = helpers;
+ const comp1 = app.createComponent(\`Dialog\`, true, true, false, true);
+
+ function slot1(ctx, node, key = \\"\\") {
+ const b2 = text(\`Before - \`);
+ const b3 = ctx[zero];
+ const b4 = text(\` - After\`);
+ return multi([b2, b3, b4]);
+ }
+
+ return function template(ctx, node, key = \\"\\") {
+ return comp1({slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx}})}, key + \`__1\`, node, this, null);
+ }
+}"
+`;
+
+exports[`slots default content is available as 0 2`] = `
+"function anonymous(app, bdom, helpers
+) {
+ let { text, createBlock, list, multi, html, toggler, comment } = bdom;
+ let { callSlot } = helpers;
+
+ function defaultContent1(ctx, node, key = \\"\\") {
+ return text(\`default content\`);
+ }
+
+ return function template(ctx, node, key = \\"\\") {
+ return callSlot(ctx, node, key, 'default', false, {}, defaultContent1.bind(this));
+ }
+}"
+`;
+
exports[`slots default content is not rendered if named slot is provided 1`] = `
"function anonymous(app, bdom, helpers
) {
diff --git a/tests/components/slots.test.ts b/tests/components/slots.test.ts
index f36ef6d0..0c3f549a 100644
--- a/tests/components/slots.test.ts
+++ b/tests/components/slots.test.ts
@@ -1933,4 +1933,17 @@ describe("slots", () => {
"1 hello
child
2 hello
child
"
);
});
+
+ test("default content is available as 0", async () => {
+ class Dialog extends Component {
+ static template = xml`default content`;
+ }
+ class Parent extends Component {
+ static template = xml``;
+ static components = { Dialog };
+ }
+
+ await mount(Parent, fixture);
+ expect(fixture.innerHTML).toBe("Before - default content - After");
+ });
});