diff --git a/wax-prosemirror-services/src/MatchingService/MatchingOptionNodeView.js b/wax-prosemirror-services/src/MatchingService/MatchingOptionNodeView.js
new file mode 100644
index 0000000000000000000000000000000000000000..f5a9656cbef57d6f32dc2a190cf89c46c5735a11
--- /dev/null
+++ b/wax-prosemirror-services/src/MatchingService/MatchingOptionNodeView.js
@@ -0,0 +1,32 @@
+import QuestionsNodeView from '../lib/helpers/QuestionsNodeView';
+
+export default class MatchingOptionNodeView extends QuestionsNodeView {
+  constructor(
+    node,
+    view,
+    getPos,
+    decorations,
+    createPortal,
+    Component,
+    context,
+  ) {
+    super(node, view, getPos, decorations, createPortal, Component, context);
+
+    this.node = node;
+    this.outerView = view;
+    this.getPos = getPos;
+    this.context = context;
+  }
+
+  static name() {
+    return 'matching_option';
+  }
+
+  stopEvent(event) {
+    if (event.target.type === 'text') {
+      return true;
+    }
+    const innerView = this.context.pmViews[this.node.attrs.id];
+    return innerView && innerView.dom.contains(event.target);
+  }
+}
diff --git a/wax-prosemirror-services/src/MatchingService/MatchingService.js b/wax-prosemirror-services/src/MatchingService/MatchingService.js
index c95696a11b9f41ef9c8726ba96fe461f7fbe91b5..77df0ee9bf0aac232c004432965edb3e974c41cf 100644
--- a/wax-prosemirror-services/src/MatchingService/MatchingService.js
+++ b/wax-prosemirror-services/src/MatchingService/MatchingService.js
@@ -1,8 +1,11 @@
 import Service from '../Service';
 import MatchingQuestion from './MatchingQuestion';
 import matchingContainerNode from './schema/matchingContainerNode';
+import matchingOptionNode from './schema/matchingOptionNode';
 import MatchingContainerNodeView from './MatchingContainerNodeView';
+import MatchingOptionNodeView from './MatchingOptionNodeView';
 import MatchingContainerComponent from './components/MatchingContainerComponent';
+import MatchingOptionComponent from './MatchingOptionComponent';
 
 class MatchingService extends Service {
   name = 'MatchingService';
@@ -16,11 +19,21 @@ class MatchingService extends Service {
       matching_container: matchingContainerNode,
     });
 
+    createNode({
+      matching_option: matchingOptionNode,
+    });
+
     addPortal({
       nodeView: MatchingContainerNodeView,
       component: MatchingContainerComponent,
       context: this.app,
     });
+
+    addPortal({
+      nodeView: MatchingOptionNodeView,
+      component: MatchingOptionComponent,
+      context: this.app,
+    });
   }
 }
 
diff --git a/wax-prosemirror-services/src/MatchingService/components/EditorComponent.js b/wax-prosemirror-services/src/MatchingService/components/EditorComponent.js
new file mode 100644
index 0000000000000000000000000000000000000000..9f4cc72aab0d59e19ef7bc41cf4962ed2b128e2f
--- /dev/null
+++ b/wax-prosemirror-services/src/MatchingService/components/EditorComponent.js
@@ -0,0 +1,180 @@
+/* eslint-disable react/prop-types */
+
+import React, { useContext, useRef, useEffect } from 'react';
+import styled from 'styled-components';
+import { EditorView } from 'prosemirror-view';
+import { EditorState, TextSelection } from 'prosemirror-state';
+import { StepMap } from 'prosemirror-transform';
+import { keymap } from 'prosemirror-keymap';
+import { baseKeymap } from 'prosemirror-commands';
+import { undo, redo } from 'prosemirror-history';
+import { WaxContext } from 'wax-prosemirror-core';
+import Placeholder from '../../MultipleChoiceQuestionService/plugins/placeholder';
+
+const EditorWrapper = styled.div`
+  border: none;
+  display: flex;
+  flex: 2 1 auto;
+  justify-content: left;
+
+  .ProseMirror {
+    white-space: break-spaces;
+    width: 100%;
+    word-wrap: break-word;
+
+    &:focus {
+      outline: none;
+    }
+
+    :empty::before {
+      content: 'Type your answer';
+      color: #aaa;
+      float: left;
+      font-style: italic;
+      pointer-events: none;
+    }
+
+    p:first-child {
+      margin: 0;
+    }
+
+    p.empty-node:first-child::before {
+      content: attr(data-content);
+    }
+
+    .empty-node::before {
+      color: rgb(170, 170, 170);
+      float: left;
+      font-style: italic;
+      height: 0px;
+      pointer-events: none;
+    }
+  }
+`;
+
+const EditorComponent = ({ node, view, getPos }) => {
+  const editorRef = useRef();
+
+  const context = useContext(WaxContext);
+  const {
+    app,
+    pmViews: { main },
+  } = context;
+  let questionView;
+  const questionId = node.attrs.id;
+  const isEditable = main.props.editable(editable => {
+    return editable;
+  });
+
+  let finalPlugins = [];
+
+  const createKeyBindings = () => {
+    const keys = getKeys();
+    Object.keys(baseKeymap).forEach(key => {
+      keys[key] = baseKeymap[key];
+    });
+    return keys;
+  };
+
+  const getKeys = () => {
+    return {
+      'Mod-z': () => undo(view.state, view.dispatch),
+      'Mod-y': () => redo(view.state, view.dispatch),
+    };
+  };
+
+  const plugins = [keymap(createKeyBindings()), ...app.getPlugins()];
+
+  // eslint-disable-next-line no-shadow
+  const createPlaceholder = placeholder => {
+    return Placeholder({
+      content: placeholder,
+    });
+  };
+
+  finalPlugins = finalPlugins.concat([
+    createPlaceholder('Type your answer'),
+    ...plugins,
+  ]);
+
+  useEffect(() => {
+    questionView = new EditorView(
+      {
+        mount: editorRef.current,
+      },
+      {
+        editable: () => isEditable,
+        state: EditorState.create({
+          doc: node,
+          plugins: finalPlugins,
+        }),
+        dispatchTransaction,
+        disallowedTools: ['Images', 'Lists', 'lift', 'MultipleChoice'],
+        handleDOMEvents: {
+          mousedown: () => {
+            main.dispatch(
+              main.state.tr
+                .setMeta('outsideView', questionId)
+                .setSelection(
+                  new TextSelection(
+                    main.state.tr.doc.resolve(
+                      getPos() +
+                        2 +
+                        context.pmViews[questionId].state.selection.to,
+                    ),
+                  ),
+                ),
+            );
+
+            context.updateView({}, questionId);
+            if (questionView.hasFocus()) questionView.focus();
+          },
+          blur: (editorView, event) => {
+            if (questionView && event.relatedTarget === null) {
+              questionView.focus();
+            }
+          },
+        },
+
+        attributes: {
+          spellcheck: 'false',
+        },
+      },
+    );
+
+    // Set Each note into Wax's Context
+    context.updateView(
+      {
+        [questionId]: questionView,
+      },
+      questionId,
+    );
+    if (questionView.hasFocus()) questionView.focus();
+  }, []);
+
+  const dispatchTransaction = tr => {
+    const { state, transactions } = questionView.state.applyTransaction(tr);
+    questionView.updateState(state);
+    context.updateView({}, questionId);
+
+    if (!tr.getMeta('fromOutside')) {
+      const outerTr = view.state.tr;
+      const offsetMap = StepMap.offset(getPos() + 1);
+      for (let i = 0; i < transactions.length; i++) {
+        const { steps } = transactions[i];
+        for (let j = 0; j < steps.length; j++)
+          outerTr.step(steps[j].map(offsetMap));
+      }
+      if (outerTr.docChanged)
+        view.dispatch(outerTr.setMeta('outsideView', questionId));
+    }
+  };
+
+  return (
+    <EditorWrapper>
+      <div ref={editorRef} />
+    </EditorWrapper>
+  );
+};
+
+export default EditorComponent;
diff --git a/wax-prosemirror-services/src/MatchingService/components/MatchingOptionComponent.js b/wax-prosemirror-services/src/MatchingService/components/MatchingOptionComponent.js
new file mode 100644
index 0000000000000000000000000000000000000000..efc17d00e85d22f08872143943820c9a7851260f
--- /dev/null
+++ b/wax-prosemirror-services/src/MatchingService/components/MatchingOptionComponent.js
@@ -0,0 +1,7 @@
+/* eslint-disable react/prop-types */
+import React from 'react';
+import EditorComponent from './EditorComponent';
+
+export default ({ node, view, getPos }) => {
+  return <EditorComponent getPos={getPos} node={node} view={view} />;
+};
diff --git a/wax-prosemirror-services/src/MatchingService/schema/matchingOptionNode.js b/wax-prosemirror-services/src/MatchingService/schema/matchingOptionNode.js
new file mode 100644
index 0000000000000000000000000000000000000000..e07647b7cc0a5f7f9c05d3f3508de4ad297f9384
--- /dev/null
+++ b/wax-prosemirror-services/src/MatchingService/schema/matchingOptionNode.js
@@ -0,0 +1,29 @@
+const matchingOptionNode = {
+  attrs: {
+    class: { default: 'matching-option' },
+    id: { default: '' },
+    correct: { default: false },
+    answer: { default: false },
+    feedback: { default: '' },
+  },
+  group: 'block questions',
+  content: 'block*',
+  defining: true,
+  parseDOM: [
+    {
+      tag: 'div.matching-option',
+      getAttrs(dom) {
+        return {
+          id: dom.getAttribute('id'),
+          class: dom.getAttribute('class'),
+          correct: JSON.parse(dom.getAttribute('correct').toLowerCase()),
+          answer: JSON.parse(dom.getAttribute('answer').toLowerCase()),
+          feedback: dom.getAttribute('feedback'),
+        };
+      },
+    },
+  ],
+  toDOM: node => ['div', node.attrs, 0],
+};
+
+export default matchingOptionNode;