set parent component for vue node views

This commit is contained in:
Philipp Kühn
2020-12-14 12:05:46 +01:00
parent 8e7659bcd1
commit aef4bd88fc
4 changed files with 46 additions and 9 deletions

View File

@@ -31,6 +31,8 @@ import * as d3 from 'd3'
import simplify from 'simplify-js' import simplify from 'simplify-js'
export default { export default {
name: 'Paper',
props: { props: {
updateAttributes: { updateAttributes: {
type: Function, type: Function,

View File

@@ -252,9 +252,7 @@ export class Editor extends EventEmitter {
this.view.updateState(newState) this.view.updateState(newState)
this.view.setProps({ this.createNodeViews()
nodeViews: this.extensionManager.nodeViews,
})
// Lets store the editor instance in the DOM element. // Lets store the editor instance in the DOM element.
// So well have access to it for tests. // So well have access to it for tests.
@@ -262,6 +260,15 @@ export class Editor extends EventEmitter {
dom.editor = this.proxy dom.editor = this.proxy
} }
/**
* Creates all node views.
*/
public createNodeViews() {
this.view.setProps({
nodeViews: this.extensionManager.nodeViews,
})
}
/** /**
* Creates a ProseMirror document. * Creates a ProseMirror document.
*/ */

View File

@@ -5,6 +5,12 @@ import { Node as ProseMirrorNode } from 'prosemirror-model'
import Vue from 'vue' import Vue from 'vue'
import { VueConstructor } from 'vue/types/umd' import { VueConstructor } from 'vue/types/umd'
function getComponentFromElement(element: HTMLElement): Vue {
// @ts-ignore
// eslint-disable-next-line
return element.__vue__
}
interface VueRendererOptions { interface VueRendererOptions {
stopEvent: ((event: Event) => boolean) | null, stopEvent: ((event: Event) => boolean) | null,
update: ((node: ProseMirrorNode, decorations: Decoration[]) => boolean) | null, update: ((node: ProseMirrorNode, decorations: Decoration[]) => boolean) | null,
@@ -132,7 +138,7 @@ class VueNodeView implements NodeView {
}, },
}) })
const props = { const propsData = {
NodeViewWrapper, NodeViewWrapper,
NodeViewContent, NodeViewContent,
editor: this.editor, editor: this.editor,
@@ -144,10 +150,13 @@ class VueNodeView implements NodeView {
updateAttributes: (attributes = {}) => this.updateAttributes(attributes), updateAttributes: (attributes = {}) => this.updateAttributes(attributes),
} }
const parent = this.editor.view.dom.parentElement
? getComponentFromElement(this.editor.view.dom.parentElement)
: undefined
this.vm = new Component({ this.vm = new Component({
// TODO: get parent component <editor-content> parent,
// parent: this.parent, propsData,
propsData: props,
}).$mount() }).$mount()
} }
@@ -258,11 +267,17 @@ class VueNodeView implements NodeView {
return return
} }
// prevents `Avoid mutating a prop directly` error message
const originalSilent = Vue.config.silent
Vue.config.silent = true
Object Object
.entries(data) .entries(data)
.forEach(([key, value]) => { .forEach(([key, value]) => {
this.vm.$props[key] = value this.vm.$props[key] = value
}) })
Vue.config.silent = originalSilent
} }
updateAttributes(attributes: {}) { updateAttributes(attributes: {}) {
@@ -295,5 +310,18 @@ class VueNodeView implements NodeView {
} }
export default function VueRenderer(component: Vue | VueConstructor, options?: Partial<VueRendererOptions>) { export default function VueRenderer(component: Vue | VueConstructor, options?: Partial<VueRendererOptions>) {
return (props: NodeViewRendererProps) => new VueNodeView(component, props, options) as NodeView return (props: NodeViewRendererProps) => {
// try to get the parent component
// this is important for vue devtools to show the component hierarchy correctly
// maybe its `undefined` because <editor-content> isnt rendered yet
const parent = props.editor.view.dom.parentElement
? getComponentFromElement(props.editor.view.dom.parentElement)
: undefined
if (!parent) {
return undefined
}
return new VueNodeView(component, props, options) as NodeView
}
} }

View File

@@ -17,7 +17,7 @@ export default Vue.extend({
if (editor && editor.options.element) { if (editor && editor.options.element) {
this.$nextTick(() => { this.$nextTick(() => {
this.$el.appendChild(editor.options.element.firstChild) this.$el.appendChild(editor.options.element.firstChild)
// editor.setParentComponent(this) editor.createNodeViews()
}) })
} }
}, },