Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(ui/core): rerender direct host child with right slot attr when root is switched #2448

Merged
merged 1 commit into from
Jan 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/great-pumas-rush.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@lion/ui': patch
---

[core] rerender direct host child with right slot attr when root is switched
15 changes: 15 additions & 0 deletions packages/ui/components/core/src/SlotMixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,21 @@ const SlotMixinImplementation = superclass =>
// Providing all options breaks Safari: we keep host and creationScope
const { creationScope, host } = this.renderOptions;
render(template, rerenderTarget, { creationScope, host, renderBefore });

// Assume we had this config:
// `'my-slot': () => ({ template: myBool ? html`<div id=a></div>` : html`<span id=b></span>`, renderAsDirectHostChild: true })`
// If myBool started as true, <div id=a></div> would be rendered in first render above, a slot would be applied,
// resulting in <div id=a slot=my-slot></div>
// However, when myBool changes to false, the <span id=b></span> would be rendered as root instead...
// We need to make sure that this "replaced root" gets the slot applied as well => <span id=b slot=my-slot></span>
const isRerenderingRootOfTemplate =
renderAsDirectHostChild &&
renderBefore.previousElementSibling &&
!renderBefore.previousElementSibling.slot;

if (isRerenderingRootOfTemplate) {
renderBefore.previousElementSibling.slot = slotName;
}
}

/**
Expand Down
50 changes: 50 additions & 0 deletions packages/ui/components/core/test/SlotMixin.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,56 @@ describe('SlotMixin', () => {
expect(isActiveElement(el._focusableNode._buttonNode, { deep: true })).to.be.true;
});

it('allows for switching template root in slot as a direct child', async () => {
const tagName = defineCE(
// @ts-expect-error
class extends SlotMixin(LitElement) {
static properties = { isSwitched: Boolean };

constructor() {
super();
this.isSwitched = false;
}

get slots() {
return {
...super.slots,
'my-root-switcher-node': () => ({
template: this.isSwitched
? html`<div id="is-switched"></div>`
: html`<span id="is-not-switched"> </span> `,
renderAsDirectHostChild: true,
}),
};
}

render() {
return html`<slot name="my-root-switcher-node"></slot>`;
}

get _myRootSwitcherNode() {
return /** @type HTMLSpanElement */ (
Array.from(this.children).find(elm => elm.slot === 'my-root-switcher-node')
);
}
},
);
const el = /** @type {* & SlotHost} */ (await fixture(`<${tagName}></${tagName}>`));

expect(el._myRootSwitcherNode.id).to.equal('is-not-switched');
expect(el.innerHTML).to.equal(
`<!--_start_slot_my-root-switcher-node_--><!----><span id="is-not-switched" slot="my-root-switcher-node"> </span> <!--_end_slot_my-root-switcher-node_-->`,
);

el.isSwitched = true;
await el.updateComplete;

expect(el._myRootSwitcherNode.id).to.equal('is-switched');
expect(el.innerHTML).to.equal(
`<!--_start_slot_my-root-switcher-node_--><!----><div id="is-switched" slot="my-root-switcher-node"></div><!--_end_slot_my-root-switcher-node_-->`,
);
});

describe('firstRenderOnConnected (for backwards compatibility)', () => {
it('does render on connected when firstRenderOnConnected:true', async () => {
// Start with elem that does not render on connectedCallback
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ export class LionInputTelDropdown extends LionInputTel {

return {
template: templates.dropdown(this._templateDataDropdown),
renderAsDirectHostChild: Boolean,
renderAsDirectHostChild: true,
};
},
};
Expand Down
Loading