Vue.js v-html contenteditable prevent dom refresh to keep cursor / caret from jumping
Asked Answered
S

2

27

For reference I'm using Vue 2.0, Vuex, and Firebase.

I am building a contenteditable component using the v-html binding to render the innerHTML. The data is updated onKeyUp. Whenever the data is updated the DOM element refreshes with the "new" data, causing the caret / cursor to jump back to the beginning of the contenteditable div.

I have looked into Rangy and a few other stackoverflow solutions, but I feel the easiest solution would be to unbind the DOM element from the data refresh. I would like for the data to still update in firebase but not result in an element refresh.

Is there a way for me to still use v-html but prevent the DOM element from refreshing with the data? Or is there another way to render the HTML without auto binding?

Edit: 11/18/16

So I’ve continued to work on a fix for this. Here are my current ideas.

  1. Use a lifecycle hook and stop component re-render. I’ve looked through the Vue docs but can’t seem to find something to stop the cycle.
  2. Use something like React’s “componentShouldRender”. Again, it doesn’t look like Vue.js has a comparable method in the lifecycle.

If anybody knows of any methods to end the lifecycle, stop re-render, or a way to get React's "componentShouldRender" functionality out of vue, that should be enough fix this issue.

-

Update: 11/29/16

This update is a little late coming. I've logged a feature request with Vue on Github.

There are a few JSFiddles in the issue discussion which could provide a potential solution. However none of them I believe qualifies as a complete solution. The only promising one has recently yielded more issues.

All of these problems would be non-issues with the addition of a componentShouldRender lifecycle hook. I will continue to look for a complete solution

Something answered 17/11, 2016 at 23:16 Comment(8)
make jsfiddle plsAlcinia
Searching for a smiliar problem, I found this in the docs : vuejs.org/v2/guide/forms.html#lazy apparently you can add :lazy to your v-model directive, in order for the model to update on change events only. It's not exactly what you're looking for, but it may help you handle itVenenose
@Venenose it's actually .lazy. but I tried it with no change :/Something
Brrrrr then I don't know I guess you'll have to plug some custom event management there. Hope someone smarter will post a solution.Venenose
If it were an input, I'd suggest re-focus after the dom's refreshed with some lifecycle hook. Not sure what's with "editable div".Cetinje
I think I answered a similar question a few weeks back which may be of use: #40151514Aeromechanic
@Aeromechanic I was able to look over that one before submitting this question. Unfortunately I don't think their case quite matches my criteria. See my update and attached JSFiddles for a better idea.Something
@Jason, did you added components to your contenteditable and stored user input to database? Did you made the ability to edit stored to database content?Willettawillette
P
5

Is there a way for me to still use v-html but prevent the DOM element from refreshing with the data?

Yes. The v-once directive does exactly this.

https://v2.vuejs.org/v2/api/#v-once

Psychotechnology answered 6/9, 2017 at 18:50 Comment(0)
C
1

As suggested by @woodberry simply add the v-once directive to the content editable div. Here is an example implementation:

<div v-once v-html="content" :contenteditable="true" @input="onInput"></div>

Then the onInput() method could handle the value changes:

onInput(event) {

    this.content = event.target.innerText
}

Then set the content as a reactive property

data() {
    return {
        content: ''
    }
},

Try the example above with and without the v-once directive to see the difference.

Coinage answered 12/5, 2022 at 15:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.