Creating NodeViews with content in Remirror

Learn how to add NodeViews with editable content in Remirror

Idriss Mahjoubi
NEXT Engineering
3 min readSep 22, 2022

--

A core concept of Remirror is NodeViews, which allow developers to add custom nodes into a document. For example, we might want to add a user card with custom styling and behavior that contains the user’s photo, name, and so on. The card would be an HTML element, rendered within the Remirror document. But what if we wanted to add editable content to this node? For example, after we add a user card, we see a “review area” as part of the card itself, where we can write a review (text) about the user.

NodeViews are the HTML representation of a Remirror Node. A more advanced NodeView with complex looks and behavior might be complex to create. Lucky for us, we can use React components to create such NodeViews.

Whether the NodeView is created from HTML elements or a ReactComponent (which is later converted into HTML by Remirror), They can have a child node that Remirror calls contentDOM — The DOM node that should hold the node’s content. In our example the “review area”

Two build-in Remirror extensions allow us to create NodeViews:

  1. Low-level method: NodeViewsExtension allows other extensions to “manually” create NodeViews (e.g. from HTML elements) which alter how the DOM is rendered for the node.
  2. High-level method: ReactComponentExtension that magically converts a React component into a NodeView by using the functionalities from the NodeViewsExtension mentioned above. This is a higher-level extension than NodeViewsExtension and is tailored to make react developers' lives easier.

If you’re not familiar with Remirror’s extensions, look at the concept of the extension in Remirror docs.

In this article, we will mainly demonstrate ReactComponentExtension functionalities and how we can use that to create a NodeView with content.

Here’s a UserNodeView with a content example. (source code)

Create a new Node without content

Let Remirror know about our node

First, Remirror needs to know the DOM representation of our node so it can render it (draw it in the document).

We create a new node custom extension called UserCardExtension that must extend the NodeExtension interface. This tells Remirror there’s a new node you don’t know about.

In our NodeSpec we set the DOM element attributes, add which type of content our node should allow and where it will be added

As you may have noticed in the example above, we don’t allow for content at all `content: ‘’`, We tell Remirror what to parse from the DOM and how to render to the DOM.

Create a NodeView for our new node using ReactComponent property

Next, we will add our custom react component to represent the user card node in the editor without content.

We assign our UserCard component to the ReactComponent property provided by the built-in ReactComponentExtension.

Congratulations, we created a UserNodeView without content.

Allow Node to have editable content

To the main objective, we will make the changes to our extension to allow for editable content in our user node.

First, we change the NodeSpec to tell Remirror to allow empty or block content.

In the example above, we allow empty or block content content: ‘block*’, and we add a zero as the last argument of the DOMOutputSpec. The number zero (a.k.a “hole”) is used to indicate that a child node can be inserted. If it occurs in an DOMOutputSpec spec, it should be the only child element in its parent node.

Finally, we set where the content will be added in our React component

Note here we pass forwardRef to the child element. This prop must be attached to the part of the tree where content will be rendered to. Once the React ref is available the forwardRef prop appends the contentDOM to the element where it was attached.

For more about why forwardRef is needed see the comment here.

Since the node accepts content, all editable elements within the node will become .. well, editable. We wrap the editable elements in a div with the attribute contentEditable=’false’ to selectively remove their editing behavior.

We now have our UserNodeView which has editable content. Building on this we can add helpers and commands to set how we want this node to behave within the document.

If you’re not using a react component for your custom node you can add content to it directly using createNodeViews like mentioned above check out the callout-extension code.

Happy Coding!

--

--