Jonas Degener
Jonas Degener

Reputation: 81

Spaces are not recognized correctly in the TipTap Editor

we use the rich text editor of TipTap in our project.
But we have the problem, that spaces are not recognized correctly and only after every 2 click a space is created. As framework we use Vue.JS.

import { Editor, EditorContent, EditorMenuBar } from 'tiptap'
import {
  HardBreak,
  Heading,
  OrderedList,
  BulletList,
  ListItem,
  Bold,
  Italic,
  History
} from 'tiptap-extensions'
import EditorMenuButton from './EditorMenuButton.vue'
export default {
  name: 'editor',
  components: {
    EditorMenuButton,
    EditorMenuBar,
    EditorContent
  },
  props: {
    value: {
      type: null,
      default: ' '
    }
  },
  data () {
    return {
      innerValue: ' ',
      editor: new Editor({
        extensions: [
          new HardBreak(),
          new Heading({ levels: [1, 2, 3] }),
          new BulletList(),
          new OrderedList(),
          new ListItem(),
          new Bold(),
          new Italic(),
          new History()
        ],
        content: `${this.innerValue}`,
        onUpdate: ({ getHTML }) => {
          this.innerValue = getHTML()
        }
      })
    }
  },
  watch: {
    // Handles internal model changes.
    innerValue (newVal) {
      this.$emit('input', newVal)
    },
    // Handles external model changes.
    value (newVal) {
      this.innerValue = newVal
      this.editor.setContent(this.innerValue)
    }
  },
  mounted () {
    if (this.value) {
      this.innerValue = this.value
      this.editor.setContent(this.innerValue)
    }
  },
  beforeDestroy () {
    this.editor.destroy()
  }
}
</script>

does anyone have any idea what could be the reason for assuming only every two spaces?

Upvotes: 8

Views: 8577

Answers (7)

lcha105u
lcha105u

Reputation: 1

Maybe you should try this.

watch: {
    // Handles external model changes.
    value (newVal) {
        // convert whitespace into \u00a0 -> &nbsp;
        let content = newVal.replace(/\s/g, "\u00a0");
        this.editor.setContent(content)
    }
},

It seems like the normal white space has been removed by html automatically. Therefore, I convert whitespace into 'nbsp;' and it's worked.

Upvotes: 0

Mert
Mert

Reputation: 554

"Okay the problem is that the watcher will get fired when you type in the editor. So this will check if the editor has focus an will only update the editor content if that's not the case."

 watch: {
    value(val) {
      if (!this.editor.focused) {
        this.editor.setContent(val, false);
      }
    }
  },

issue: https://github.com/ueberdosis/tiptap/issues/776#issuecomment-667077233

Upvotes: 1

Rik De Peuter
Rik De Peuter

Reputation: 713

We had the same problem, we kept the onUpdate trigger but changed the watch so that it would only invoke editor.setContent when the value was actually different.

  watch: {
    value() {
      let html = this.editor.getHTML();
      if (html !== this.value) {
        this.editor.setContent(this.value);
      }
    },
  },

Upvotes: 4

Emozio
Emozio

Reputation: 31

Remove onUpdate section and the bug will disapear. I don't know why, but it's interesting to know how to reproduce the bug.

That does help. Following this advice, I am currently using the onBlur event instead of onUpdate, while obtaining the content's HTML using the editor instance and the getHTML() function, as such: this.editor.getHTML().

(In my case I $emit this value in order for it to be reactive to my parent component, but that may be irrelevant for the original question).

Upvotes: 3

Dylan Hanner
Dylan Hanner

Reputation: 9

This bug for me was caused by doing something like this:

  watch: {
    value: {
      immediate: true,
      handler(newValue) {
        this.editor.setContent(newValue)
      },
    },
  },

Removed this entirely and the bug went away. Maybe this will help someone in future.

Upvotes: 0

Lo&#239;c Griveau
Lo&#239;c Griveau

Reputation: 29

Remove onUpdate section and the bug will disapear. I don't know why, but it's interessing to know how to reproduce the bug. However if you create a "minimal reproductible example" the bug does not appear. So what ? I don't know.

I found a workaround which is to use vuex.

Rather than assign the value returned by getHTML() in the innerValue variable and then issue an 'input' event, I put this value in the store.

Upvotes: -1

realAlexBarge
realAlexBarge

Reputation: 1888

The code you provided seems to be working just fine. So the issue most likely is produced by a side effect in either your code or some dependency.

To debug this issue you could look for event listeners, especially regarding key press or key down events and looking if you are checking for space key specifically somewhere (event.keyCode === 32 or event.key === " "). In conjunction with event.preventDefault this could explain such an issue.

Another more broad way to debug this is to strip away parts from your code until the bug disappears or add to a minimal example until the bug appears.

Upvotes: -1

Related Questions