Force toDom to be re-executed

Is there a way to force the view to rebuild the dom? I have a toDOM for a node where the value of an attribute is generated. e.g. (node) => [“p”, {style: “margin-left:” + node.attrs.marginCount * this.marginSize + “px”}, 0]

So when the value of my marginSize changes I want the nodes to update. Since the attrs itself is not being updated it doesn’t look like the node(s) have changed so I can understand why it’s not automatic. So I tried going through update/setProps on the view and the UpdateStateInner only does that if it determines updateDoc to be true which only happens if either the nodeViews have changed or the doc differs from the ViewDesc’s doc instance.

I was going to try and go the route of a doc level attribute similar to discussed here but that seems like its mutating the doc instance itself. And I don’t see any intrinsic way to mutate a doc’s attrs correctly and really I don’t know that I want that since presumably that will go into the undo history and this is not an undoable action but more of rendering state. So at this point my only approach is to have a dummy nodeView that I create a shallow clone of and use setProps to register the new nodeViews but I’m hoping there’s a cleaner approach that I’m overlooking.

This comes up now and then, and the solution so far has been to toggle some kind of node decoration on all nodes that need to be redrawn. That works, but it’s somewhat awkward. Another option would be to use setProps to change the set of active node views. That will force the view to redraw. It requires any one of the node view constructors to be different (could be just a different copy of the same function). Does that help?

Thanks. The latter sounds like what I’m doing currently - a shallow clone of a dummy/unused nodeView so that updateDoc is true. That seems to have the downside of the selection and scroll position being reset/lost but I’m trying to hack around that by caching the selection and scrollTop prior to this change and restore that after the setProps. It’s kludgy but works. I would try the decoration approach if that would avoid those issues. Do you know of a sample/example that does that? I’m sure you’re busy and I appreciate the reply so I’ll hunt around to find one unless you’re aware of one off the top of your head.

I don’t have an example, but basically you iterate the document to find the nodes you need to refresh, and add a (somehow non-equal to any other deco) node decoration to each. Then you can set up your node view update methods to recognize this decoration and do the updating necessary (or just return false for a full node redraw). The next update can drop the deco again.

Ah I see. Thx. I’m not actually using custom node views at this point. Just the toDOM but I may investigate that approach. Thanks for the suggestion.

Hi Andrews, Have you happened to figure out how to do this? Any example code on it?

I ended up using a custom css property since my target browsers all support that and then I didn’t have to do anything to the nodes or the dom representation of them. So my style looks more like the following: “margin-left:calc(var(--custom-margin-size)*” + node.attrs.marginCount + “);”

1 Like

Thank you for the reply! I got it. That makes sense in this case.