qwik
qwik copied to clipboard
Slot fallback not working
Qwik Version
qwik: 0.0.101, qwik-city: 0.0.101
Operating System (or Browser)
MacOS Monterey 12.3.1 / Chrome 104.0.5112.79
Node Version (if applicable)
14.19.1
Which component is affected?
Qwik Runtime
Expected Behaviour
Fallback slot showing
Actual Behaviour
Fallback slot not showing
Additional Information
on typescript error: Type '{ children: string; name: string; }' is not assignable to type 'IntrinsicAttributes & { name?: string; }'. Property 'children' does not exist on type 'IntrinsicAttributes & { name?: string; }'.(2322)
also tried it on the playground and it's not working
Since 0.0.100 we removed the extra dom node for host components and slots. This made it very complicated to support fallback content, however now it's easier to target and implement yourself fallback content with css. We might add fallback later.
@manucorporat ah I see, thank you for the info
Perhaps the tutorial should be updated to reflect this.
@manucorporat what is the plan for fallback? The only real alternative is to pass content as a prop and then render that, but that's quite ugly
Here's the tutorial solution if you do it like that:
export const Card = component$<{renderBody?, renderTitle?}>(({renderBody, renderTitle}) => {
useStyles$(CSS);
const title = renderTitle ? renderTitle() || "fallbackTitle" : <Slot name="title"/>
const body = renderBody ? renderBody() || <div>fallback body</div> : <Slot/>
return (
<div class="card">
<div class="title">
{title}
</div>
<div class="body">
{body}
</div>
</div>
);
});
export const App = component$(() => {
return (
<>
<Card>
<span q:slot="title">Qwik</span>
<span>Qwik is a resumable framework for building instant web apps.</span>
</Card>
<Card renderTitle={()=>"Partytown"} renderBody={()=>{}}>
</Card>
<Card>
<span>
Builder.io allows you to visually build on your tech stack Empower your entire team to
visually create and optimize high-speed experiences on your sites and apps. Provide
whole-team autonomy with a platform that is developer approved.
</span>
</Card>
</>
);
});
or is there a nicer way?
Actually, those render functions can't rerender when they depend on changing data. I'm not even sure how to do that correctly.
So, the way you can do it is something like this (note the additional css div and the sibling selector in the CSS):
import { component$, Slot, useStyles$ } from '@builder.io/qwik';
export const Card = component$(() => {
useStyles$(CSS);
return (
<div class="card">
<div class="title">
<Slot name="title"></Slot>
</div>
<div class="body">
<Slot></Slot>
</div>
<div class="body fallback">Fallback content</div>
</div>
);
});
export const App = component$(() => {
return (
<>
<Card>
<span q:slot="title">Qwik</span>
<span>Qwik is a resumable framework for building instant web apps.</span>
</Card>
<Card>
<span q:slot="title">Partytown</span>
</Card>
<Card>
<span>
Builder.io allows you to visually build on your tech stack Empower your entire team to
visually create and optimize high-speed experiences on your sites and apps. Provide
whole-team autonomy with a platform that is developer approved.
</span>
</Card>
</>
);
});
export const CSS = `
.card {
border-radius: 5px;
vertical-align: top;
display: inline-block;
border: 1px solid grey;
width: 200px;
margin: .5em;
}
.title {
background-color: lightgray;
padding: 0.5em;
border-bottom: 1px solid black;
}
q\\:fallback {
color: gray;
}
.body {
padding: 0.5em;
}
.body:empty {
display: none;
}
.body.fallback {
display: none;
}
.body:empty + .body.fallback {
display: block;
}
`;
That's great thanks! I was thinking we had to use content but this is way easier.
It's still not optimal though, if you have content and it will never change, then the html contains the fallbacks for all those cards for no reason.
EDIT: Actually, doing it with CSS is straightforward, so if it's simply text, the solution is this:
.title:empty::before {
content: 'Fallback title'
}
Yeah, would be helpful if there were a way to check if the "slot" were empty using script or something. I'm a bit too busy to look into this in depth myself, but if I come across some time I may see if I can figure out a better way and submit
@csdswarm I think you're already in a good position to update the tutorial so that new users aren't confused...
While waiting for a better solution, I have updated the tutorial #1817
Hi @O-Hooman , @wmertens , @csdswarm and @forresst 👋 Should we keep this bug open or would it make sense to create a new feature request issue for it?
@zanettin yea it's more make sense if create it as a request for a new feature
Thanks for your reply @O-Hooman 🙏 would you like to formulate it as an enhancement and close this issue afterwards? thanks a lot for your help 🙏