Search code examples
javascriptnpmimportsvelterollupjs

How to use LeaderLine with Svelte?


I'm new to Svelte and I'm trying to use LeaderLine with a Svelte application. I managed to import it with import LeaderLine from 'leader-line';, but unfortunately the example which is given on the package page doesn't work:

<script>
  import LeaderLine from 'leader-line';

  new LeaderLine(
    document.getElementById('start'),
    document.getElementById('end')
  );    
</script>

<div id="start">start</div>
<div id="end">end</div>

In the browser console I'm getting this error: Uncaught (in promise) Error: start and end are required.

I think it's because of the usage of getElementById, what if I'm right we normally don't want to do in Svelte. So I want to ask you guys if you have an idea how to get LeaderLine + Svelte running together. Any ideas appreciated!


Solution

  • You need to wrap the LeaderLine initialization in onMount. The code in the script tag runs before the component has been added to the DOM, so document.getElementById('start') returns null. onMount will run after the component has been added to the DOM.

    <script>
      import LeaderLine from 'leader-line';
      import { onMount } from 'svelte';
    
      onMount(() => {
        new LeaderLine(
          document.getElementById('start'),
          document.getElementById('end')
        );
      });
    </script>
    

    While you can use getElementId in Svelte, it would be Svelte-ier to bind to the start and end elements.

    <script>
      import LeaderLine from 'leader-line';
      import { onMount } from 'svelte';
    
      let start, end;
      onMount(() => {
        new LeaderLine(start, end);
      });
    </script>
    
    <div bind:this={start}>start</div>
    <div bind:this={end}>end</div>
    

    Also, I assume you figured this out if you got the "start and end are required" error, but I had to use @rollup/plugin-legacy with the following Rollup configuration to build the app since leader-line doesn't export anything.

    export default {
      // ... other config
      plugins: [
        // ... other plugins
        legacy({ 'node_modules/leader-line/leader-line.min.js': 'LeaderLine' }),
      ]
    };