-
Notifications
You must be signed in to change notification settings - Fork 783
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(runtime): hide slotted content with no destination in scoped comp…
…onents (#5135) * fix(runtime): re-relocate slot if parent element's tagname changes If a slot is located in an element and that element's tag is dynamically changed (e.g. from `p` to `span`), we need to re-relocate the slot on re-render STENCIL-672: slot element loses its parent reference and disappears when its parent is rendered conditionally Fixes: #4284, #3913 * add e2e tests * code documentation * put changes behind slot fix flag * resolve new SNC * reset `hidden` state of nodes on relocate It is possible for slotted content to still be invisible in the DOM if the slot was not rendered on the first render. This commit resets the `hidden` attribute of a node on successful relocation. STENCIL-1053 * hide slot content without a home in `scoped` components Hides any content that is projected through to a Stencil component that does not have a destination slot. Only for `scoped` components. Fixes #2877 STENCIL-938 * add e2e tests for hiding content without a slot * revert karma config * PR feedback Co-authored-by: Christian Bromann <git@bromann.dev> --------- Co-authored-by: Christian Bromann <git@bromann.dev>
- Loading branch information
1 parent
735d45a
commit 77bce27
Showing
7 changed files
with
192 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { Component, h, Host, Prop } from '@stencil/core'; | ||
|
||
@Component({ | ||
tag: 'slot-hide-content-open', | ||
scoped: false, | ||
shadow: false, | ||
}) | ||
export class SlotHideContentOpen { | ||
@Prop() enabled = false; | ||
|
||
render() { | ||
return ( | ||
<Host> | ||
<p>Test</p> | ||
{this.enabled && ( | ||
<div class="slot-wrapper"> | ||
<slot> | ||
<span>fallback default slot</span> | ||
</slot> | ||
</div> | ||
)} | ||
</Host> | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { Component, h, Host, Prop } from '@stencil/core'; | ||
|
||
@Component({ | ||
tag: 'slot-hide-content-scoped', | ||
scoped: true, | ||
}) | ||
export class SlotHideContentScoped { | ||
@Prop() enabled = false; | ||
|
||
render() { | ||
return ( | ||
<Host> | ||
<p>Test</p> | ||
{this.enabled && ( | ||
<div class="slot-wrapper"> | ||
<slot> | ||
<span>fallback default slot</span> | ||
</slot> | ||
</div> | ||
)} | ||
</Host> | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<!doctype html> | ||
<meta charset="utf8" /> | ||
<script src="./build/testapp.esm.js" type="module"></script> | ||
<script src="./build/testapp.js" nomodule></script> | ||
|
||
<slot-hide-content-scoped class="test-cmp"> | ||
<p id="slotted-1">Hello</p> | ||
</slot-hide-content-scoped> | ||
|
||
<slot-hide-content-open class="test-cmp"> | ||
<p id="slotted-2">Hello</p> | ||
</slot-hide-content-open> | ||
|
||
<button type="button">Enable slot</button> | ||
|
||
<script> | ||
document.querySelector('button').addEventListener('click', () => { | ||
document.querySelectorAll('.test-cmp').forEach((ref) => ref.setAttribute('enabled', true)); | ||
}); | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { setupDomTests, waitForChanges } from '../util'; | ||
|
||
/** | ||
* Tests for projected content to be hidden in a `scoped` component | ||
* when it has no destination slot. | ||
*/ | ||
describe('slot-hide-content', function () { | ||
const { setupDom, tearDownDom } = setupDomTests(document); | ||
let app: HTMLElement | undefined; | ||
let host: HTMLElement | undefined; | ||
|
||
beforeEach(async () => { | ||
app = await setupDom('/slot-hide-content/index.html'); | ||
}); | ||
|
||
afterEach(tearDownDom); | ||
|
||
describe('scoped encapsulation', () => { | ||
it('should hide content when no slot is provided', async () => { | ||
host = app.querySelector('slot-hide-content-scoped'); | ||
const slottedContent = host.querySelector('#slotted-1'); | ||
|
||
expect(slottedContent).toBeDefined(); | ||
expect(slottedContent.hasAttribute('hidden')).toBe(true); | ||
expect(slottedContent.parentElement.tagName).toContain('SLOT-HIDE-CONTENT-SCOPED'); | ||
|
||
document.querySelector('button').click(); | ||
await waitForChanges(); | ||
|
||
expect(slottedContent.hasAttribute('hidden')).toBe(false); | ||
expect(slottedContent.parentElement.classList).toContain('slot-wrapper'); | ||
}); | ||
}); | ||
|
||
describe('no encapsulation', () => { | ||
it('should not hide content when no slot is provided', async () => { | ||
host = app.querySelector('slot-hide-content-open'); | ||
const slottedContent = host.querySelector('#slotted-2'); | ||
|
||
expect(slottedContent).toBeDefined(); | ||
expect(slottedContent.hasAttribute('hidden')).toBe(false); | ||
expect(slottedContent.parentElement.tagName).toContain('SLOT-HIDE-CONTENT-OPEN'); | ||
|
||
document.querySelector('button').click(); | ||
await waitForChanges(); | ||
|
||
expect(slottedContent.hasAttribute('hidden')).toBe(false); | ||
expect(slottedContent.parentElement.classList).toContain('slot-wrapper'); | ||
}); | ||
}); | ||
}); |