Skip to content
QuireKit
Core docs
Alpha · evolving API
Extension developmentView Markdown ↗

Build an interactive NodeView

Add a button to a persistent counter node and connect rendering, positions, transactions and cleanup.

A Node defines saved data. A NodeView defines editing interaction. This chapter uses the DOM backend to add a +1 button to a counter block. Canvas/SVG require layout and selection adapters; this DOM button is not automatically a canvas node.

1. Store count in the document

docsCounter is a block atom with no editable children. Its count attribute defaults to 0. JSON stores the count; renderHTML() emits a static element rather than the editing button.

core/node-view/counter.tsts

Install createCounterNode(), then insert { type: 'docsCounter', attrs: { count: 0 } }. atom: true treats it as one unit; it does not install format conversion or layout support. This example supplies no Markdown, DOCX or AI contract.

2. Read the current position and node on click

Edits before the counter move its position. Each click calls getPos(), then incrementDocsCounter(position). The command reads the current node and count from tr.doc, checks type, numeric bounds and editability, then updates attributes.

Do not capture the initial count and repeatedly write initialCount + 1, or cache the first getPos() result. Without dispatch, the command only validates availability, so can().incrementDocsCounter(position) does not increment.

3. Keep the view synchronized with content

core/node-view/view.tsts

update(next) receives a new immutable node. It updates and returns true for the same type; false asks the view to rebuild for another type. contentEditable=false keeps the button outside text input, while stopEvent assigns button events to the control.

This atom has no contentDOM, so its own button changes can be ignored. A NodeView with editable children needs contentDOM and must allow editor-owned input and selection changes; do not reuse this example's unconditional ignoreMutation() there. destroy() removes the listener this view created.

4. Try it and inspect saved content

Preparing the example…

Click +1 twice to reach 2. Undo returns to 0 or the preceding history group. Download JSON and inspect attrs.count; it must not contain button DOM. Insert a paragraph before the counter and verify that clicking still changes the same node. The preview's source tab includes the mounting component; node and view sources can be read independently.

The example command enforces read-only mode so the button cannot modify a read-only document. More complex controls also need keyboard access, focus restoration, selected appearance, and cancellation/failure handling for external requests.

QuireKitQuireKit · Core, plugins and Classic docs