VUE-COMPOSITION-API: why does ref not feel reactive on contenteditable

Viewed 318

After I insert an image to the contenteditable, I notice the ref() can't "catch up" the inserted image to the text.

  1. Go to: https://codesandbox.io/s/zealous-ardinghelli-b05ph
  2. Place cursor to text
  3. Click the "INSERT IMAGE BETWEEN TEXT" button
  4. Pay attention to the shown ref() below the button
const insertImgTag = () => {
      const image =
        '<img class="separator" src="/text-image.png" width="27px" height="19px">';

      let sel, range, node;
      if (window.getSelection) {
        sel = window.getSelection();
        if (sel.getRangeAt && sel.rangeCount) {
          range = window.getSelection().getRangeAt(0);
          node = range.createContextualFragment(image);
          range.insertNode(node);
        }
      } else if (document.selection && document.selection.createRange) {
        document.selection.createRange().pasteHTML(image);
      }
    };

enter image description here

notice on the image above, the shown ref() still counts the <img> as one instead of two like the text

1 Answers

The problem is somehow, I don't get the event in the component. This is definitively not a ref() problem. But anyway, universal event forwarding is completely "hacky" with vue2 (you'll notice in contenteditable source code I have to manually forward all the events...)

So, Two options :

  1. I invite you to try with Vue3 (I stopped further developpment of vue-contenteditable for Vue2, only the Vue3 version is maintained)

  2. If you really can't move to vue 3, then you can use this hack to "patch" your problem :

<div id="app">
    <contenteditable
+++   ref="ce"
      v-model="string"
      tag="p"
      class="text-data"
[...]
--- setup() {
+++ setup(props, {refs}) {
[...]
    const insertImgTag = () => {
      const image =
        '<img class="separator" src="/text-image.png" width="27px" height="19px">';

      let sel, range, node;
      if (window.getSelection) {
        sel = window.getSelection();
        if (sel.getRangeAt && sel.rangeCount) {
          range = window.getSelection().getRangeAt(0);
          node = range.createContextualFragment(image);
          range.insertNode(node);
        }
      } else if (document.selection && document.selection.createRange) {
        document.selection.createRange().pasteHTML(image);
      }
+++   string.value = refs.ce.current_content();
    };

https://codesandbox.io/s/lucid-glitter-8c4qp?file=/src/App.vue (note :the {refs} in setup is a vue-compositionapi hack because the vue3 way of doing it can't be implemented with vue2)

Related