I want to iterate over nodes, so I can sync them to a database, so I need to give each nodes a unique id.
This is my progress so far.
TodoItem.js (tiptap extension)
import { Node } from 'tiptap'
import { splitToDefaultListItem, liftListItem } from 'tiptap-commands'
import TodoItemComponent from './TodoItemComponent'
import uuid from 'uuid'
export default class TodoItem extends Node {
get name() {
return 'todo_item'
}
get view() {
return TodoItemComponent
}
get schema() {
return {
attrs: {
blockId: {
default: uuid.v4() // *problem* it keeps the same value on all created node
},
done: {
default: false
},
},
draggable: true,
content: 'paragraph',
toDOM: node => {
const { blockId, done } = node.attrs
return [
'li',
{
'data-type': this.name,
'data-done': done.toString(),
'data-block-id': blockId
},
['span', { class: 'todo-checkbox', contenteditable: 'false' }],
['div', { class: 'todo-content' }, 0],
['div', { class: 'todo-actions', contenteditable: 'false' }],
]
},
parseDOM: [{
priority: 51,
tag: `[data-type="${this.name}"]`,
getAttrs: dom => ({
blockId: dom.getAttribute('data-block-id') || uuid.v4(), // this works on loading editor content
done: dom.getAttribute('data-done') === 'true',
}),
}],
}
}
}
TodoItemComponent.vue
<template>
<li class="todo"
:data-block-id="node.attrs.blockId"
:data-type="node.type.name"
:data-done="node.attrs.done.toString()"
>
<span class="todo-checkbox" contenteditable="false" @click="onChange"></span>
<div class="todo-content" ref="content" :contenteditable="editable.toString()"></div>
</li>
</template>
<script>
export default {
props: ['node', 'updateAttrs', 'editable', 'view', 'getPos'],
methods: {
onChange() {
this.updateAttrs({
done: !this.node.attrs.done,
})
},
},
}
</script>
BlockId attrs is same between different node.
BlockId attrs should be unique
Adding Plugin to the node resolve my problem
default node attrs for blockId changed to null
get plugins() {
return [
new Plugin({
appendTransaction: (transactions, oldState, newState) => {
const newTr = newState.tr
let modified = false
newState.doc.descendants((node, pos) => {
if (!!node.type && (node.type.name === 'todo_item')) {
const { blockId, ...rest} = node.attrs
if (blockId === undefined || blockId === null || blockId === '') {
// Adds a unique id to a node
newTr.setNodeMarkup(pos, undefined, { blockId: uuid.v4(), ...rest })
modified = true
}
}
})
if (modified) {
return newTr
}
}
})
]
}
This plugin is useful for anyone need to add some attributes to new nodes
Most helpful comment
Adding Plugin to the node resolve my problem
default node attrs for blockId changed to
nullThis plugin is useful for anyone need to add some attributes to new nodes