Create a NodeView for multiple choice quizzes

I am trying to build a custom node view for creating multiple choice quizzes. Users would be able to add them like any other content to their documents. They would look something like this:

 +----------------------------------------------------+                       
 | Question:                                          |                       
 | +------------------------------------------------+ |                       
 | | What is the answer to all questions?           | |                       
 | +------------------------------------------------+ |                       
 |                                           Correct? |                       
 | +-----------------------------------------+  +--+  |                       
 | | 41                                      |  |  |  |                       
 | +-----------------------------------------+  +--+  |                       
 | +-----------------------------------------+  +--+  |                       
 | | 42                                      |  |X |  |                       
 | +-----------------------------------------+  +--+  |                       
 | +-----------------------------------------+  +--+  |                       
 | | Type your answer…                       |  |  |  |                       
 | +-----------------------------------------+  +--+  |                       
 |                                                    |                       
 | Explanation                                        |   
 | +------------------------------------------------+ |                       
 | |Provide an explanation                          | |                       
 | +------------------------------------------------+ |                       
 +----------------------------------------------------+                                                                             

They would consist of a text field for the question and the explanation. In between there would be three text field for the answers and a checkbox to mark the answer as correct.

I am wondering what would be the best way to approach this problem. I figured that a NodeView is the way to go. If I understand the design of contentDOM correctly, this works for one and only one text input area while I have five.

I saw that the footnote tutorial uses inner views for which is initialises sub-instances of the EditorView. Adopting this approach, I can draw a single sub-editor and retrieve its content as the content of the quiz node.

Yet I don’t understand whether it is possible to use several sub-instances and store their content in the quiz node’s content.

I would try modeling it closely to that of a todo list and todo items: TaskList – Tiptap Editor

You can go two directions — if you want ProseMirror to manage the content of your choices (allowing WYSIWYG editing inside them), you’ll probably want to create something similar to a list in your schema, and may not even need a node view, just a number of custom commands to manipulate the node. Another approach would be to have the node view be entirely self-contained, handling the editing of choices with its own custom logic. Then you wouldn’t need contentDOM at all, and the outer editor can treat it like a leaf node.

Thank you @bhl and @marijn for taking the time looking into this.

I tried out the first route described by @marijn and I think that was a great hint. It really helped me understand how standard nodes can be composed.

Here’s the implementation: Glitch :・゚✧

There are a few things that puzzle me though:

  1. If you click into the third question, there’s no cursor unless you type something.
  2. How would I allow the user to add a node after a quiz if the quiz is the last node in a document? I guess the prosemirror-gapcursor could do, but I cannot get that to run by hitting for example ArrowDown in the explanation box.
  3. What would be a good way to move the controls (“Delete Quiz”, “Toggle Correct”) from the menu into the node, e.g. using a checkbox to mark an answer as correct?

For completeness sake, here are the answers that I found for my problems:

  1. The cursor re-appears when display:flex on div.answer is removed.
  2. If I understand correctly, GapCursors can only be shown after leaf nodes. In my example the node type quiz is not a leaf node as it has content. This can be fixed by adding an atom: true attribute to the quiz node.
  3. Taking the example of Details – Tiptap Editor (the arrow for showing and hiding is actually a button), I think adding a button with an event listener and passing the view and dispatch should do the trick, but I haven’t tried that yet.

Hi Alexander,

I’m trying to implement exactly the same sort of NodeView, I checked your ‘Glitch’ link but it’s not working. Do you have an implementation example anywhere else?

1 Like