Skip to content
  1. Tutorials

Ogma + Svelte/Vite

For the integration with Svelte, we used the recommened Svelte-ts + Vite template. It helped us to bootstrap a Svelte application very quickly, with the TypeScript support out of the box.

Unfortunately, you cannot start right away from the StackBlitz playground, because Ogma package is only avaliable through our private downaload center at get.linkurio.us. So we have downloaded the template and just added a sample Ogma.svelte component, that reads the shared counter state and adds nodes as you click on the "Increment" button.

For that we will have to use some special Svelte component tricks:

  • We need to implement lazy initialization of Ogma
  • We would need to isolate the component so that you could control it from the outside using the shared state.

Ogma component

We add a new component in src/lib/Ogma.svelte, that would create the Ogma container and interact with the rest of the UI.

First, lets add the container and styling:

html
<script lang="ts"></script>
<div id="container"></div>
<style>
  #container {
    width: 400px;
    height: 400px;
    margin: auto;
    border: 1px solid #ccc;
  }
</style>

That would add the <div> element to the DOM, and adds styles to it. Now we need to initialize Ogma inside the <div> element in a lazy manner.

For that we will be using Svelte's use:action.

ts
import Ogma from '@linkurious/ogma';

// action
function setup(node: HTMLDivElement) {
  const ogma = new Ogma({
    container: node.getAttribute('id'),
    graph: {
      nodes: [{ id: 0 }],
      edges: []
    }
  });
  // add styles
  ogma.styles.addNodeRule({
    text: {
      content: 'node',
      position: 'center',
      color: 'white'
    }
  });
  return {
    destroy() {
      // kill ogma instance when the container is removed from DOM
      return ogma.destroy();
    }
  };
}

And when we connect it to the template, we just need to use it as an action:

html
<div id="container" use:setup></div>

This way when the container is mounted, it will call the component lifecycle function setup and pass the <div> element as a parameter. This is where we instantiate Ogma and add styles to it. It returns the destroy hook where we can take care of the destruction of the Ogma instance.

Connecting the component to the state

For this example we will be using the simplest possible state, just a counter. Svelte has a built-in way to share state between components. Let's declare the state and the in the src/lib/state.ts file:

ts
import { writable } from 'svelte/store';

export const count = writable(1);

export function increment() {
  count.update(v => (v = v + 1));
}

Here we expose the counter state and the function to increment it. We will use this counter to create nodes in the graph. A button in the UI will increment the counter and Ogma component will be notified and create a new node.

In the button component, we will use the count state to show how many nodes are in the graph and the increment function to increment the counter.

html
<script lang="ts">
  import { count, increment } from './state';
</script>

<button on:click="{increment}">Nodes: {$count}</button>

Let's now use the counter state in the Ogma component to create nodes. For that, first we need to set the count as a dependency of the Ogma component action.

html
<script lang="ts">
  import { count } from './state'
  import Ogma from '@linkurious/ogma';

  // action
  function setup (node: HTMLDivElement) {
    ...
    return {
      update(count: number) {
        return ogma.addGraph({
          nodes: [{ id: count }],
          edges: [{ source: 0, target: count }]
        }).then(() => ogma.layouts.force({ locate: true }));
      },
      destroy() {
        ...
      }
    }
  }
</script>
<!-- pass the count as a dependency -->
<div id="container" use:setup="{$count}"></div>

And that's it, now when we click on the button, nodes are created in the Ogma component, and we also re-run the layout.

Svelte app

You can download the source code of the Svelte app here.