fix(ui/core): rerender direct host child with right slot attr when root is switched
This commit is contained in:
parent
81e2a1d2d1
commit
5344fdeb66
4 changed files with 71 additions and 1 deletions
5
.changeset/great-pumas-rush.md
Normal file
5
.changeset/great-pumas-rush.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@lion/ui': patch
|
||||
---
|
||||
|
||||
[core] rerender direct host child with right slot attr when root is switched
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ export class LionInputTelDropdown extends LionInputTel {
|
|||
|
||||
return {
|
||||
template: templates.dropdown(this._templateDataDropdown),
|
||||
renderAsDirectHostChild: Boolean,
|
||||
renderAsDirectHostChild: true,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue