Aaron Meese
Aaron Meese

Reputation: 2213

How to dynamically populate svelte-simple-modal component?

I have the following in my Modal.svelte file:

<script>
  import Modal from "svelte-simple-modal";
  import { modalState } from "$lib/stores";

  const imports = {
    Person: () => import("./modals/Person.svelte")
  };
</script>

<Modal>
  {#if $modalState.open}
    {#await imports[$modalState.type]() then module}
      <svelte:component this={module.default} />
    {/await}
  {/if}
</Modal>

And this is what is in my stores.js file:

import { writable } from "svelte/store";

export const modalState = writable({
  open: true,
  type: "Person",
});

This renders the contents of the passed modalState.type file (which is modals/Person.svelte) perfectly, but the content isn't nested in the Modal element whatsoever. There is no popup, no close button, and no greyed-out background.

How do I make sure the contents of the imported component are part of the Modal and not just added to the page like a non-modal component?

Upvotes: 1

Views: 1675

Answers (2)

Aaron Meese
Aaron Meese

Reputation: 2213

I was able to get this solved by making the following changes to the Modal.svelte file:

<script>
  // @ts-nocheck
  import { writable } from "svelte/store";
  import Modal from "svelte-simple-modal";
  import { modalState } from "$lib/stores";

  const modal = writable(null);
  const imports = {
    Person: () => import("./modals/Person.svelte")
  };

  $: if ($modalState.open) {
    (async () => {
      const module = await imports[$modalState.type]();
      modal.set(module.default);
    })();
  }
</script>

<Modal show={$modal} />

Additional information can be found in this GitHub thread.

Upvotes: 1

brunnerh
brunnerh

Reputation: 184376

The API of that package is fairly unintuitive. The Modal either is used as a scope that can be interacted with via a context, or by using a special bind function and passing the resulting component to show.

It does not show the contents of the Modal in the dialog.

E.g. with bind:

<script>
    import Modal, { bind } from '[email protected]';
    import Popup from './Popup.svelte';

    let modal = null;
    $: open = modal != null;
    const showModal = () => modal = bind(Popup, { message: 'Surprise' });
</script>

<Modal show={modal} on:close={() => modal = null} />
<button on:click={showModal}>Show modal</button>

{open ? 'Opened' : 'Closed'}

REPL

You could rewrite the store to directly return a compatible component for show or use something like derived to return a component dependent on open.

Upvotes: 1

Related Questions