How can I communicate from a plugin to a custom nodeView?

when the node attributes of the custom nodeView change and therefore the underlying doc changes, I just replace the node and all works as expected.

But now I would like to communicate to the nodeView, without actually changing the node. So I tried to set from my plugin a node decoration on that nodeview (putting my payload into the spec argument). Unfortunately at my custom nodeView, the update method (where I expect to get access to the payload in the decoration spec object) never gets called. Is there anything fundamentally wrong with that approach ?

1 Like

That approach should work, but I’ve never actually done it, so it might be that something is broken. Does the decoration get applied? (If you add, say, a class name, does it show up in the DOM?)

@marijn, thanks, it works perfectly and as expected, I just had a stupid typo at invoking the method for adding a decoration to the decoration set.

Is this the recommended way to communicate from a plugin to a NodeView?

I have a similar situation where a plugin gets external data that various NodeViews use. I need those NodeViews to update (re-render) themselves when that external data changes. So I really just need a way to tell prosemirror to re-render the NodeViews.

From this thread it seems possible to decorate the NodeViews and then update the decorations when the external data changes. The decoration change will then trigger prosemirror to re-render the NodeViews. It seems like a round about way to force a re-render but if its the best way then I’ll do it.

Yes.

2 Likes

@rsaccon

Hi Roberto, I am wondering how you got this to work? When I change the decoration prop in a plugin, my nodeViews do not get their update() method called, and when the update() method is called, my decorations argument is always an empty array.

To illustrate I remixed the linter example here: Glitch :・゚✧ I figured the linter example is a good one to use since it has lots of decorations.

The relevant code I added was

line 105

nodeViews: {
        blockquote (node, view, getPos, decorations) { 
            return new BlockView(node, view, getPos, decorations);
        }
    },

and the nodeview

line 84

class BlockView {
    constructor(node, view, getPos, decorations) {
        this.node = node;
        this.getPos = getPos;
        this.dom = document.createElement('blockquote');
        this.contentDOM = this.dom;
    }
    update(node, decos) {
        console.log('decos', decos);

        this.node = node;
        return true;
    }
}

When I run the example and create a blockquote nodeView, the decorations are not passed in the update method. Also, if the decorations are changed via the plugin, update() is not called on the nodeView. I have seen the same outcome for several examples I have run, not just the remixed example above.

I think I am missing something here. Are you directly calling the update() method on the nodeView? Any insights would be greatly appreciated.

I just went through this same issue, in my case it was because the positions that I was providing to the decoration weren’t exactly aligned with the node. These dev tools https://github.com/d4rkr00t/prosemirror-dev-tools helped me a lot in terms of understanding the document structure and node positions.

Before that I was fudging the decoration positions back and forth +/- 1 until I got them to show up in the update parameters.

2 Likes