I’m still relatively new with prosemirror. I have this custom node definition :
const editorTitle = { name: 'editorTitle', content: 'text*', isTextblock: true, attrs: { class: { default: 'editorTitleId' }, }, group: 'block', parseDOM: [ { priority: 51, // must be higher than the default image spec tag: 'div[class]', getAttrs(dom) { const nodeClass = dom.getAttribute('class'); if (nodeClass != 'editorTitleId') { return false; } return true; }, }, ], toDOM(node) { return ['div', { class: 'editorTitleId' }, 0]; }, };
and this related custom node view :
class editorTitleView { setDataBeforeContent(outer, textContent) { const dataBeforeContent = textContent ? '' : 'Untitled item'; outer.setAttribute('data-before-content', dataBeforeContent); } findNodePosition(doc, target, not) { let result = -1; doc.descendants((node, pos) => { const condition = not ? target !== node : target === node; if (condition) { result = pos; return false; } }); return result; } constructor(node, view, getPos) { const vm = this; const outer = document.createElement('div'); outer.textContent = textContent; outer.classList.add('editorTitleId'); outer.setAttribute('contenteditable', true); vm.setDataBeforeContent(outer, textContent); $(outer).on('keydown paste', ev => { const { currentTarget, keyCode, type, originalEvent, ctrlKey } = ev; const isPaste = type == 'paste'; if (![8, 46, 17].includes(keyCode) && (!ctrlKey || isPaste)) { const clipboardData = originalEvent.clipboardData || window.clipboardData; let value = clipboardData && isPaste ? clipboardData.getData('text') : undefined; if (!isPaste) { value = currentTarget.value; } let { tr, doc } = view.state; const _node = doc.content.content[0]; const nodeStartPos = vm.findNodePosition(doc, _node); const { type } = _node; if (type.name == 'editorTitle') { if (nodeStartPos != -1) { tr = tr.setNodeMarkup( nodeStartPos, undefined, { value: value }, ); view.updateState(view.state.apply(tr)); } else { console.error('nodeStartPos == -1 !!!!!!!!'); } } } }); setTimeout(() => { outer.focus(); }, 150); vm.dom = outer; } ignoreMutation() { return true; } update(node, decorations) { return false; } selectNode() { console.log('editorTitleView :: selectNode '); } }
FYI , i’m using ‘use-prosemirror’, so this is how i pass mySchema
const mySchema = new Schema({ nodes: { ...nodes, resizableImage, editorTitle }, marks: schema.spec.marks, }); const [state, setState] = useProseMirror({ doc: DOMParser.fromSchema(mySchema).parse(prevsioulyPersistedContent goes here..), schema: mySchema, plugins: [ keymap(baseKeymap), ], }); <ProseMirror state={state} dispatchTransaction={transaction => { console.log('dispatchTransaction '); const { view } = useProseMirrorComp; let newState = view.state.apply(transaction); persistContentInBackend(state, newState, mySchema, props); view.updateState(newState); }} ref={r => { useProseMirrorComp = r; }} nodeViews={getNodeViews(resizableImage, editorTitle)} > <div id="content" /></ProseMirror>
The initial display is fine but then when i just click on the dom element generated by the custom view i get this error
Uncaught TypeError: Cannot read property 'previousSibling' of undefined at domIndex (index.js:34) at CustomNodeViewDesc.localPosFromDOM (index.js:782) at NodeViewDesc.posFromDOM (index.js:822) at posFromCaret (index.js:336) at posAtCoords (index.js:406) at EditorView.posAtCoords$1 [as posAtCoords] (index.js:4885) at handlers.mousedown (index.js:3523) at HTMLDivElement.view.dom.addEventListener.view.eventHandlers.<computed> (index.js:3295)
Somebody has a clue why it does happen ?