Categories
Svelte

Sharing Code Between Svelte Component Instances with Module Context

Spread the love

Svelte is an up and coming front end framework for developing front end web apps.

It’s simple to use and lets us create results fast.

In this article, we’ll look at how to share variables between component instances with module context.

Module Context

Svelte components can contain code that is shared between multiple component instances.

To do this, we can declare the script block with context='module' . The code inside it will run once, when the module first evaluates, rather than when a component is instantiated.

For instance, we can use it to create multiple audio elements that can only have one audio element play at a time by stopping the ones that aren’t being played as follows:

App.svelte :

<script>
  import AudioPlayer from "./AudioPlayer.svelte";
</script>

<AudioPlayer
  src="https://file-examples.com/wp-content/uploads/2017/11/file_example_MP3_700KB.mp3"
/>

<AudioPlayer
  src="https://file-examples.com/wp-content/uploads/2017/11/file_example_MP3_1MG.mp3"
/>

<AudioPlayer
  src="http://www.hochmuth.com/mp3/Haydn_Cello_Concerto_D-1.mp3"
/>

AudioPlayer.svelts :

<script context="module">
  let current;
</script>

<script>
  export let src;

  let audio;
  let paused = true;

  const stopOthers = () =>{
    if (current && current !== audio) current.pause();
    current = audio;
  }
</script>

<article>
  <audio
    bind:this={audio}
    bind:paused
    on:play={stopOthers}
    controls
    {src}
  ></audio>
</article>

In the code above, we have the AudioPlayer component which has the code that’s shared between all instances in:

<script context="module">
  let current;
</script>

This lets us call pause on any instance of the audio element that isn’t the one that’s being played as we did in the stopOthers function. stopOthers is run when we click play on an audio element.

Then we included the AudioPlayer instances in the App.svelte component.

Therefore, when we click play on one of the audio elements, we pause the other ones.

Exports

Anything that’s exported from a context='module' script block becomes an export of the module itself. For instance, we can create a button to stop all the audio elements in AudioPlayer that is currently playing as follows:

App.svelte :

<script>
  import AudioPlayer, { stopAll } from "./AudioPlayer.svelte";
</script>

<button on:click={stopAll}>Stop All</button>

<AudioPlayer
  src="https://file-examples.com/wp-content/uploads/2017/11/file_example_MP3_700KB.mp3"
/>

<AudioPlayer
  src="https://file-examples.com/wp-content/uploads/2017/11/file_example_MP3_1MG.mp3"
/>

<AudioPlayer
  src="http://www.hochmuth.com/mp3/Haydn_Cello_Concerto_D-1.mp3"
/>

AudioPlayer.svelte :

<script context="module">
  let elements = new Set();

  export const stopAll = () => {
    elements.forEach(element => {
      element.pause();
    });
  };
</script>

<script>
  import { onMount } from 'svelte';
  export let src;
  let audio;

  onMount(() => {
    elements.add(audio);
    return () => elements.delete(audio);
  });
</script>

<article>
  <audio
    bind:this={audio}
    controls
    {src}
  ></audio>
</article>

In the code above, we add all the audio element instances to the elements set which we created in the contex='module' block as each AudioPlayer component is mounted.

Then we export the stopAll function, which has all the audio element instances from elements , and we call pause on all of them by looping through them and calling pause .

In App.svelte , we import the stopAll function from AudioPlayer and then call it when we click the Stop All button.

Then when we click play on one or more audio elements, they’ll all be paused when we click the Stop All button.

Note that we can’t have a default export because the component is the default export.

Conclusion

We can use the module context script block to add script blocks that are shared between all instances of a component.

If we export functions inside module context script blocks, we can import the function and then call it.

Leave a Reply

Your email address will not be published. Required fields are marked *