Reputation: 18299
I have a child Button that I want to reuse. This button contains the code to check whether the user has permissions to use the Button. In one parent, I just want to display the button as is, and this works fine. However in a different component, I want to wrap the button in a Card, and conditionally display both the Card and the Button depending on whether the user is authorized.
Child Component:
<script>
let isAuthorized = false;
async function updateIsAuthorized() {
isAuthorized = await hasPermission('CREATE_FOO');
}
onMount(isAuthorized);
</script>
{#if isAuthorized}
<Button>...</Button>
{/if}
The following Parent of course will display an empty Card if the user doesn't have permissions to use the Button. Instead, I want to hide the Card in this case, so this is no good:
<script>
import FooButton from './FooButton.svelte';
// ...
</script>
<Card>
<FooButton>
</Card>
I did try adding an isAuthorized boolean to the parent (and export let isAuthorized to the child), and binding it, but this does not work:
<script>
import FooButton from './FooButton.svelte';
// ...
let isAuthorized = false;
</script>
{#if isAuthorized}
<Card>
<FooButton bind:isAuthorized>
</Card>
{/if}
I assume the problem here is that becuase isAuthorized
default to false, the FooButton
is never rendered, so the child component never has a chance to modify the bound isAuthorized
.
Upvotes: 0
Views: 853
Reputation: 16451
I don't think there is a really elegant solution to this, as you would be wrapping the button based on a state that is internal to this button.
The only way I see for solving this is to flip the entire thing around and extend your Button component to be able to render the Card itself (depending on some flag perhaps).
<script>
export let isCard = false;
let isAuthorized
</sccript>
{#if isAuthorized}
{#if isCard}
<Card>
<button>...</button>
</Card>
{:else}
<button>...</button>
{/if}
{/if}
You could make this slightly more dynamic if you allow passing in a component as the 'Card'
<script>
export let cardComponent;
let isAuthorized
</script>
{#if isAuthorized}
{#if cardComponent}
<svelte:component this={cardComponent}>
<button>...</button>
</svelte:component>
{:else}
<button>...</button>
{/if}
{/if}
In the last case the usage would be something like:
<script>
import Button from '...';
import Card from '...';
</script>
<Button cardComponent={Card} />
with Card
the card you want to show, with a <slot>
element where the button should go.
Upvotes: 0