Skip to content

Latest commit

 

History

History
138 lines (103 loc) · 4.68 KB

File metadata and controls

138 lines (103 loc) · 4.68 KB

Flexible Editor Content

Serialize Flexible Editor JSON content with interactive components.

Installation

Since this is included in the Flexible Editor package, you can install it the same way.

# Using npm
npm install directus-extension-flexible-editor
# Using yarn
yarn add directus-extension-flexible-editor
# Using pnpm
pnpm add directus-extension-flexible-editor

Usage

The Flexible Editor Content tools are available via directus-extension-flexible-editor/content.

At the time of writing this package only provides a Vue component to render your content. But, because it depends on tiptap-render-view, it also provides types and tools to build components for your prefered JavaScript framework.

Fetching and transforming the API data

This is for usage with relation nodes.

Since the editor field (e.g. description) and the corresponding “M2A Reference Field” (e.g. editor_nodes) are separate fields, add both fields (including the related fields) in your Directus API request as usual.

With injectDataIntoContent() you can merge both fields:

import { injectDataIntoContent } from "directus-extension-flexible-editor/content";

const data = await fetchDirectusData();

injectDataIntoContent(data.editor_nodes, data.description);

// Optionally remove editor_nodes from the payload after injecting into the description
delete data.editor_nodes;

Tip: In Nuxt you will call injectDataIntoContent in the transform callback to cache the result.

Importing Flexible Editor extensions

It might be useful to import an array of all tiptap extensions used by Flexible Editor and required for serialization.

import { serializers } from "directus-extension-flexible-editor/content";

Note: When using the FlexibleEditorContent component, these extensions are added by default.

Vue

Check out this example on StackBlitz

<template>
    <FlexibleEditorContent
        :content="data.description"
        :componentSerializers="componentSerializers"
        :relationBlocks="relationBlocks"
    />
</template>

<script setup lang="ts">
    import FlexibleEditorContent, {
        VueComponentSerializers,
        VueRelationBlockSerializers,
    } from "directus-extension-flexible-editor/content/vue";
    import { injectDataIntoContent } from "directus-extension-flexible-editor/content";
    import Textfield from "./components/Textfield.vue";
    import DefinitionList from "./components/DefinitionList.vue";
    import Video from "./components/Video.vue";

    // Fetching and transforming the API data
    const data = await fetchDirectusData();
    injectDataIntoContent(data.editor_nodes, data.description);
    delete data.editor_nodes;

    // Define components to render the relation blocks
    const relationBlocks: VueRelationBlockSerializers = [
        { collection: "definition_list", component: DefinitionList },
        { collection: "video", component: Video },
    ];

    // Define other components to render any editor content node
    const componentSerializers: VueComponentSerializers = [
        // marks with `type: 'mark'`
        { name: "italic", type: "mark", component: Textfield },
        {
            name: "bold",
            type: "mark",
            render: (attrs) => [
                Textfield,
                { ...attrs, style: "background:lightgreen" },
            ],
        },
        // blocks
        { name: "heading", render: (attrs) => ["textarea", attrs] },
    ];
</script>

Example of a component (./components/DefinitionList.vue) rendering a relation block:

<template>
    <dl>
        <template v-for="(item, key) in data.items" :key="key">
            <dt>{{ item.term }}</dt>
            <dd>{{ item.definition }}</dd>
        </template>
    </dl>
</template>

<script setup lang="ts">
    import { defineProps } from "vue";
    import type { RelationBlockProps } from "directus-extension-flexible-editor/content";

    defineProps<{
        id: RelationBlockProps["id"];
        junction: RelationBlockProps["junction"];
        collection: RelationBlockProps["collection"];
        data?: RelationBlockProps["data"];
    }>();
</script>

Other Frameworks

Feel free to contribute

Contribution

Contributions are welcome. Make sure to open an issue for bugs or start a discussion for feature requests, before you start writing code!