Reputation: 5801
I'm trying to use tiptap
as a child component and pass its content to the parent's v-model
but tiptap's documentation only seems to provide info on how to do this without script setup
, which uses a different API.
This is my parent
component:
<template>
<cms-custom-editor v-model:modelValue="state.content"/>
<p>{{state.content}}</p>
</template>
<script setup>
import CmsCustomEditor from '../../components/backend/cms-custom-editor.vue'
import {reactive} from "vue";
const state = reactive({
content: '<p>A Vue.js wrapper component for tiptap to use <code>v-model</code>.</p>',
})
</script>
and this the child
component with tiptap
:
<template>
<div id="cms-custom-editor" class="cms-custom-editor">
<editor-content :editor="editor"/>
</div>
</template>
<script setup>
import {useEditor, EditorContent} from '@tiptap/vue-3'
import StarterKit from '@tiptap/starter-kit'
const props = defineProps({
modelValue: {
type: String,
default: ''
}
})
const emit = defineEmits(['update:modelValue'])
const editor = useEditor({
extensions: [StarterKit],
content: props.modelValue,
onUpdate: () => {
emit('update:modelValue', editor.getHTML())
}
})
</script>
As soon as I type something into the editor field, this code line fails:
emit('update:modelValue', editor.getHTML())
and throws this error:
Uncaught TypeError: editor.getHTML is not a function
at Editor2.onUpdate (cms-custom-editor.vue?t=1654253729389:28:42)
at chunk-RCTGLYYN.js?v=89d16c61:11965:48
at Array.forEach (<anonymous>)
at Editor2.emit (chunk-RCTGLYYN.js?v=89d16c61:11965:17)
at Editor2.dispatchTransaction (chunk-RCTGLYYN.js?v=89d16c61:12252:10)
at EditorView.dispatch (chunk-RCTGLYYN.js?v=89d16c61:9138:27)
at readDOMChange (chunk-RCTGLYYN.js?v=89d16c61:8813:8)
at DOMObserver.handleDOMChange (chunk-RCTGLYYN.js?v=89d16c61:8924:77)
at DOMObserver.flush (chunk-RCTGLYYN.js?v=89d16c61:8575:12)
at DOMObserver.observer (chunk-RCTGLYYN.js?v=89d16c61:8455:14)
I've used the approach from the docs (chapter 5. v-model), which like I said, is not designed for script setup
.
Upvotes: 5
Views: 3742
Reputation: 221
You can try this
<script setup>
import { useEditor, EditorContent } from '@tiptap/vue-3'
import StarterKit from '@tiptap/starter-kit'
import { onBeforeUnmount, watchEffect } from 'vue';
const props = defineProps({
modelValue: {
type: String,
default: ''
}
});
const emits = defineEmits(['update:modelValue'])
watchEffect(() => props.modelValue, (newValue, oldValue) => {
const isSame = newValue === oldValue;
if (isSame) {
return;
}
editor.value?.commands.setContent(newValue, false)
});
const editor = useEditor({
content: props.modelValue,
extensions: [
StarterKit,
],
onUpdate: ({ editor }) => {
let content = editor.getHTML()
emits('update:modelValue', content)
},
});
onBeforeUnmount(() => {
editor.destroy();
})
</script>
Upvotes: 3
Reputation: 5801
Man, the docs are confusing. They mix up standard composition api
and script setup
. Anyway this is how it works:
const editor = useEditor({
extensions: [StarterKit],
content: props.modelValue,
onUpdate: ({editor}) => {
emit('update:modelValue', editor.getHTML())
}
})
Upvotes: 14