Allow Node to Dispatch Transaction to Change Node Attributes



I have ProseMirror rendering a node that is a react component. The react component allows the user to select an itemName. When the user selects an itemName I want to set the itemName attribute of the node to match the itemName that was selected by the user. In react, I would pass a function to the child component and invoke it with the necessary parameters. I have not found the proper way to do this in ProseMirror.

I know the function will need state, dispatch, and the itemName string. The following code works as a command bound to a keystroke, but will only set itemName to a hardcoded value, as I cannot figure out how to pass a parameter to a command bound to a key.

 const setItemName = (state, dispatch ) => {
       if (state.selection instanceof NodeSelection) {
         let {$from } = state.selection
       //dispatch a transaction to set the itemName attribute of the targetNode
       dispatch($from.pos, null, {...node.attrs, itemName: ‘hardcoded string’ }))
       return true

Also, I cannot figure out how to invoke a command from inside the node.

What is the proper approach? Should it be a command? Do I need to write a plugin to perform this function? If so, how can I allow a node to invoke the function, pass itemName, and dispatch the transaction?

I tried passing state and dispatch as attrs and invoking dispatch from inside the component, but state seems to be a static object and I can’t get the reference to the current node selection that way.

 const acceptor = {
       inline: true,
       attrs: {
         itemName: {default: null},
         itemType: {default: null},
       group: "inline",
       draggable: true,
       parseDOM: [{getAttrs: function getAttrs(dom) {
         return {
           itemName: dom.getAttribute("itemName"),
           itemType: dom.getAttribute("itemType"),
       toDOM(node) { let dom = document.createElement("span")
       render(<Acceptor {...node.attrs}/>, dom)
       return dom }


It’s probably easiest to use a node view for the node around the component. That gets passed an editor view and a function with which it can determine the node’s position in the document. That tends to be enough to implement actions that change the node—something like editorView.dispatch(, ...)).


Thanks, that worked!

Here’s the code I came up with:

import React from 'react';
import ReactDOM from 'react-dom';
import {Node} from "prosemirror-model";
import {EditorView, NodeView} from "prosemirror-view";
import AnyReactComponent from '../../AnyReactComponenet';

class ReactComponentView {
  constructor(node, view, getPos) {
    this.node = node
    this.view = view
    this.getPos = getPos
    this.itemType = node.attrs.itemType;
    this.itemName = node.attrs.itemName;
    const span = document.createElement('span');
        ReactDOM.render(<AnyReactComponent {...node.attrs}
          setItemName={(itemName) => this.setItemName(itemName)}/>, span);
        return {
            dom: span,

  setItemName = itemName => {
        {...this.node.attrs, itemName }


export default ReactComponentView;