What do I need for the EditorView to work?

Hello! I’m starting out my journey to creating my own prosemirror editor view, and I am feeling really dumb getting stuck at the “create a new basic EditorView” part.

It seems like I am missing a key piece of the editor still, but I can’t tell what I’m missing. My best guess is that there is an issue with the initial doc (or lack thereof), but my understanding is the view will auto-generate the default initial doc from the schema. That or I’m missing some plugin to handle events, but I’m pretty sure I have all the plugins from the examples I’ve seen.

I’ve go the following (condensed from multiple files) code for creating a new editor.

  const { blockquote, ...basicNodes } = schema.nodes;
  const schema = new Schema({
    nodes: basicNodes,
    marks: basicMarks,
  });
  const plugins = [
    history(),
    keymap({ 'Mod-z': undo, 'Mod-y': redo }),
    keymap(baseKeymap),
    dropCursor(),
    gapCursor(),
    this.observer, // logging plugin
  ];
    this.editor = new EditorView(this.host.nativeElement, {
      state: EditorState.create({
        doc: this.docNode, // Null, blank document should be auto generated from schema
        plugins: this.plugins,
        schema: baseSchema, // base schema based off prosemirror-schema-basic
      }),
    });

However, when I click inside the editor to start typing, I get the following errors

ERROR TypeError: targetNode is null
    MouseDown vendor.js:58135
    mousedown vendor.js:58102
    event vendor.js:57908
    invokeTask polyfills.js:7596
    onInvokeTask vendor.js:40301
    invokeTask polyfills.js:7596
    onInvokeTask vendor.js:40601
    invokeTask polyfills.js:7596
    runTask polyfills.js:7398
    invokeTask polyfills.js:7673
    invokeTask polyfills.js:8797
    globalCallback polyfills.js:8827
    globalZoneAwareCallback polyfills.js:8858
    customScheduleGlobal polyfills.js:8946
    scheduleTask polyfills.js:7586
    onScheduleTask vendor.js:40294
    scheduleTask polyfills.js:7581
    onScheduleTask polyfills.js:7498
    scheduleTask polyfills.js:7581
    scheduleTask polyfills.js:7437
    scheduleEventTask polyfills.js:7462
    makeAddListener polyfills.js:9097
    initInput vendor.js:57907
    EditorView vendor.js:59857
    createEditor rtea-editor.component.ts:37
    ngOnInit rtea-editor.component.ts:51
    callHook vendor.js:19430
    callHooks vendor.js:19403
    executeInitAndCheckHooks vendor.js:19360
    refreshView vendor.js:27059
    refreshComponent vendor.js:28059
    refreshChildComponents vendor.js:26843
    refreshView vendor.js:27095
    detectChangesInternal vendor.js:28198
    detectChanges vendor.js:28673
    tick vendor.js:41746
    _loadComponent vendor.js:41782
    bootstrap vendor.js:41721
    _moduleDoBootstrap vendor.js:41369
    _moduleDoBootstrap vendor.js:41369
    bootstrapModuleFactory vendor.js:41340
    invoke polyfills.js:7569
    onInvoke vendor.js:40612
    invoke polyfills.js:7569
    run polyfills.js:7352
    scheduleResolveOrReject polyfills.js:8430
    invokeTask polyfills.js:7596
    onInvokeTask vendor.js:40301
    invokeTask polyfills.js:7596
    onInvokeTask vendor.js:40601
    invokeTask polyfills.js:7596
    runTask polyfills.js:7398
    drainMicroTaskQueue polyfills.js:7767
    promise callback*nativeScheduleMicroTask polyfills.js:7744
    scheduleMicroTask polyfills.js:7754
    scheduleTask polyfills.js:7588
    scheduleTask polyfills.js:7437
    scheduleMicroTask polyfills.js:7456
    scheduleResolveOrReject polyfills.js:8420
    then polyfills.js:8611
    bootstrapModule vendor.js:41364
    4431 main.ts:6
    __webpack_require__ runtime.js:23
    __webpack_exec__ main.js:544
    <anonymous> main.js:545
    O runtime.js:57
    <anonymous> main.js:546
    webpackJsonpCallback runtime.js:145
    <anonymous> main.js:2
vendor.js:25178:19
ERROR RangeError: Position 1 out of range
    resolve vendor.js:49321
    resolveCached vendor.js:49348
    resolve vendor.js:49679
    selectionFromDOM vendor.js:57109
    readDOMChange vendor.js:59522
    domObserver vendor.js:59855
    flush vendor.js:59314
    onSelectionChange vendor.js:59242
    invokeTask polyfills.js:7596
    onInvokeTask vendor.js:40301
    invokeTask polyfills.js:7596
    onInvokeTask vendor.js:40601
    invokeTask polyfills.js:7596
    runTask polyfills.js:7398
    invokeTask polyfills.js:7673
    invokeTask polyfills.js:8797
    globalCallback polyfills.js:8827
    globalZoneAwareCallback polyfills.js:8858
    customScheduleGlobal polyfills.js:8946
    scheduleTask polyfills.js:7586
    onScheduleTask vendor.js:40294
    scheduleTask polyfills.js:7581
    onScheduleTask polyfills.js:7498
    scheduleTask polyfills.js:7581
    scheduleTask polyfills.js:7437
    scheduleEventTask polyfills.js:7462
    makeAddListener polyfills.js:9097
    connectSelection vendor.js:59222
    start vendor.js:59207
    focus vendor.js:58478
    event vendor.js:57908
    invokeTask polyfills.js:7596
    onInvokeTask vendor.js:40301
    invokeTask polyfills.js:7596
    onInvokeTask vendor.js:40601
    invokeTask polyfills.js:7596
    runTask polyfills.js:7398
    invokeTask polyfills.js:7673
    invokeTask polyfills.js:8797
    globalCallback polyfills.js:8827
    globalZoneAwareCallback polyfills.js:8858
    customScheduleGlobal polyfills.js:8946
    scheduleTask polyfills.js:7586
    onScheduleTask vendor.js:40294
    scheduleTask polyfills.js:7581
    onScheduleTask polyfills.js:7498
    scheduleTask polyfills.js:7581
    scheduleTask polyfills.js:7437
    scheduleEventTask polyfills.js:7462
    makeAddListener polyfills.js:9097
    initInput vendor.js:57907
    EditorView vendor.js:59857
    createEditor rtea-editor.component.ts:37
    ngOnInit rtea-editor.component.ts:51
    callHook vendor.js:19430
    callHooks vendor.js:19403
    executeInitAndCheckHooks vendor.js:19360
    refreshView vendor.js:27059
    refreshComponent vendor.js:28059
    refreshChildComponents vendor.js:26843
    refreshView vendor.js:27095
    detectChangesInternal vendor.js:28198
    detectChanges vendor.js:28673
    tick vendor.js:41746
    _loadComponent vendor.js:41782
    bootstrap vendor.js:41721
    _moduleDoBootstrap vendor.js:41369
    _moduleDoBootstrap vendor.js:41369
    bootstrapModuleFactory vendor.js:41340
    invoke polyfills.js:7569
    onInvoke vendor.js:40612
    invoke polyfills.js:7569
    run polyfills.js:7352
    scheduleResolveOrReject polyfills.js:8430
    invokeTask polyfills.js:7596
    onInvokeTask vendor.js:40301
    invokeTask polyfills.js:7596
    onInvokeTask vendor.js:40601
    invokeTask polyfills.js:7596
    runTask polyfills.js:7398
    drainMicroTaskQueue polyfills.js:7767
    promise callback*nativeScheduleMicroTask polyfills.js:7744
    scheduleMicroTask polyfills.js:7754
    scheduleTask polyfills.js:7588
    scheduleTask polyfills.js:7437
    scheduleMicroTask polyfills.js:7456
    scheduleResolveOrReject polyfills.js:8420
    then polyfills.js:8611
    bootstrapModule vendor.js:41364
    4431 main.ts:6
    __webpack_require__ runtime.js:23
    __webpack_exec__ main.js:544
    <anonymous> main.js:545
    O runtime.js:57
    <anonymous> main.js:546
    webpackJsonpCallback runtime.js:145
    <anonymous> main.js:2
vendor.js:25178:19

Any help would be appreciated. I haven’t been able to find anything on what the bare minimum required to have a functional text editor to compare against (just being able to type as a starting point). I have created a repo with my full setup here. GitHub - Tezraine/prosemirror-rtea: Angular Rich Text Editor Application

This looks wrong. You’re taking NodeType objects and then using them as NodeSpec. You’ll want to work with schema.spec.nodes, which holds the node specs. But that’s an OrderedMap so you can’t destructure it like this.

Oh, I didn’t notice that all of the spec interfaces accept {} as a valid value, making them compatible with anything as long as it doesn’t have a conflicting field type. Need to get in a better habit of explicitly checking types even in strict mode. Swapping out for schema.spec.nodes.remove('blockquote') fixed it. (I only was removing blockquote because I also made a simple mark version, so needed to remove one or the other, and the mark one needs to be tested)

It would be a breaking change, but something you could add in version 2 is a type discriminator field to the interfaces so that typescript knows they aren’t interchangeable. (and would also make it much easier to tell them apart if you have a function that can work with a node or mark spec, like a toggle function (learning how to toggle is my next step!)).

Thank you!