How is component inheritance done in Svelte?

99 Views Asked by At

I currently have a Modal.svelte component that uses native , I would like to create another component called ModalSheet.svelte whose parent is Modal.svelte.

Is this possible in Svelte without conflicts? Let's say I want to take advantage of all the functions already built into the parent component (Modal.svelte) in the child component (ModalSheet.svelte) and also add new functions in ModalSheet.

I also want to be able to use both and in the same page at the same time. I don't know to what extent it is possible.

Modal.svelte file:

<script>
  export let backdropClose;
  export let modalId;
  export let modalClass;
  export let labelledby;
  export let label;
  export let modal;

  let content;
  const isModal = typeof modal === "string" ? modal !== "false" : true;

  export function openModal() {
    if (content) {
      if (isModal) {
        content.showModal();
        return;
      }
      content.show();
    }
  }

  export function closeModal() {
    if (content) {
      content.close();
    }
  }

  function handleClick(event) {
    if (content && isModal && backdropClose === "true") {
      const rect = content.getBoundingClientRect();
      if (
        event.clientX < rect.left ||
        event.clientX > rect.right ||
        event.clientY < rect.top ||
        event.clientY > rect.bottom
      ) {
        content.close();
      }
    }
  }
</script>

<dialog
  aria-label={label}
  aria-labelledby={labelledby}
  id={modalId}
  class={modalClass || "ph-modal"}
  bind:this={content}
  on:click={handleClick}
>
  <slot />
</dialog>

<style lang="scss">
  dialog {
    border: 0;
    border-radius: 8px;
    background-color: #fff;
    &::backdrop {
      background-color: rgba(0, 0, 0, 0.5);
    }
  }
</style>
1

There are 1 best solutions below

0
brunnerh On

There is no real inheritance if you want to use regular component syntax, only composition.
So the specialized modal can only internally use the generic modal.

You can can use {...$$restProps} to pass on any not explicitly set properties to the base component.
Events can be forwarded by just setting on:event without specifying a handler.

For functions you probably will have to wrap/re-export them, e.g.

<script>
  // ...

  let modal;

  export function openModal() { modal.openModal() }
  // etc.
</script>
<Modal bind:this={modal} {...$$restProps}>
  <slot />
</Modal>

You could also export the internal modal instance as a property so it can be used more directly, though that breaks encapsulation.