Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Perspective with Next.js, Vue, Svelte and Angular

<perspective-viewer> is a standard Web Component, so it works in any framework which can render a DOM element and call a method on it. React has a dedicated wrapper; elsewhere, use the element directly.

Three rules apply everywhere:

  1. Initialize WebAssembly once, before first use, as described in Importing with or without a bundler.
  2. Client-side only. Perspective needs Web Workers and WebAssembly, so it cannot be server-rendered.
  3. load() is a method, not an attribute. Get a reference to the element and call viewer.load(table); use viewer.restore(config) for configuration.

Next.js

Load the component with next/dynamic and ssr: false, so Perspective is only imported in the browser:

import dynamic from "next/dynamic";

const Report = dynamic(() => import("../components/Report"), { ssr: false });

components/Report.tsx then uses @perspective-dev/react as normal.

Vue

Tell the template compiler that perspective-viewer is a custom element:

// vite.config.js
vue({
    template: {
        compilerOptions: {
            isCustomElement: (tag) => tag.startsWith("perspective-"),
        },
    },
});
<script setup>
import { onMounted, ref } from "vue";

const viewer = ref(null);
onMounted(async () => {
    await viewer.value.load(table);
    await viewer.value.restore({ group_by: ["Region"] });
});
</script>

<template>
    <perspective-viewer ref="viewer"></perspective-viewer>
</template>

Svelte

<script>
    import { onMount } from "svelte";

    let viewer;
    onMount(async () => {
        await viewer.load(table);
    });
</script>

<perspective-viewer bind:this={viewer}></perspective-viewer>

Angular

Add CUSTOM_ELEMENTS_SCHEMA to the component or module, and reach the element with @ViewChild:

@Component({
    selector: "app-report",
    template: `<perspective-viewer #viewer></perspective-viewer>`,
    schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class ReportComponent implements AfterViewInit {
    @ViewChild("viewer") viewer!: ElementRef;

    async ngAfterViewInit() {
        await this.viewer.nativeElement.load(table);
    }
}

Cleaning up

When the component unmounts, call viewer.delete(), and delete() any View and Table you created, in that order. See Cleaning up resources.