-
-
Notifications
You must be signed in to change notification settings - Fork 244
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
v-model:content not working when changed the binding value #188
Comments
@erhuabushuo |
Solved this problem like this (vue 3 with TS): Updated 2022-11-12
|
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
Didn't work for me @thedomeffm , because cursor moved to the beginning for some reason when i started typing <script lang="ts" setup>
import Quill from 'quill'
import {onMounted, ref, watch} from 'vue'
const props = defineProps<{
modelValue: string|null
syncValue?: string|null
}>()
const emits = defineEmits(['update:modelValue'])
const div = ref(null)
let quill = null
onMounted(() => {
quill = new Quill(div.value, {
theme: 'snow'
})
quill.on('text-change', () => {
console.log('--- text change', quill.root.innerHTML)
emits('update:modelValue', quill.root.innerHTML)
})
})
let _syncValue = props.syncValue
watch(props, (newP) => {
console.log('--- sync value, new and old', newP.syncValue, _syncValue)
if (newP.syncValue === _syncValue) {
return
}
let delta = quill.clipboard.convert(newP.syncValue)
quill.setContents(delta, 'api')
_syncValue = newP.syncValue
})
</script>
<template>
<div class="quill-wrapper" ref="div"></div>
</template> |
This one is a significant issue, as it's spected to work as usual with v-models. |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
As can be seen with Issue #275, people still don't understand the behaviour of the editor! |
when use v-model and contentType is html , when props value changes and the editor did not show corerctly, and I try to use pasteHtml to set. the cursor act weirdly |
It's so trivial to fix the reactivity with an intermediate variable, I can make a PR |
Please!!! |
As common practice, changes on v-model are not reflected in the editor. You can fix this problem by calling quilljs's internal API directly. (Use refs) This solution is based on the assumption that contents are provided via props. <template>
<QuillEditor ref="quill" theme="snow" toolbar="essential" v-model:content="data.contents" content-type="delta"/>
</template>
<script>
import { QuillEditor } from '@vueup/vue-quill'
import '@vueup/vue-quill/dist/vue-quill.snow.css'
export default {
name: 'editor-component',
components: { QuillEditor },
props: {
data: {
type: Object,
default: null,
},
},
data() {
return {
data: {
id: null,
contents: '',
},
}
},
watch: {
data: {
deep: true,
handler(newData, prevData) {
this.data = {
id: newData.id,
// contents: JSON.parse(newData.contents),
}
this.updateEditor(JSON.parse(newData.contents)) // delta json string from server
},
},
},
computed: {
},
methods: {
updateEditor(delta) {
this.$refs.quill.setContents(delta)
},
},
}
</script>
<style scoped lang="less">
</style> |
Not common and not intended, props should be reactive, the common behavior of a v-model is to have 2 way binding, using refs is just a workaround (which btw did you try it? You're going to have infinite update issues like this with a watcher, because the watcher will trigger on v-model update and reupdate the content etc, you're also gonna have the cursor jumping to the begining of the editor everytime you type) I made the PR to fix the bug already, it works very well and addresses all this, hopefully will be merged soon enough |
🎉 This issue has been resolved in version 1.0.1 🎉 The release is available on: Your semantic-release bot 📦🚀 |
There's still seemingly no way to wrap // RichTextEditor.vue
<template>
<ClientOnly>
<QuillEditor
class="editor"
:placeholder="placeholder"
theme="bubble"
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
</ClientOnly>
</template>
<script setup lang="ts">
import '@vueup/vue-quill/dist/vue-quill.bubble.css';
defineProps({
modelValue: {
type: String,
default: '',
required: true,
},
placeholder: {
type: String,
default: '',
required: false,
},
});
defineEmits(['update:modelValue']);
if (!process.server) {
const { QuillEditor } = await import('@vueup/vue-quill');
const { vueApp } = useNuxtApp();
if (!vueApp._context.components.QuillEditor) {
vueApp.component('QuillEditor', QuillEditor);
}
}
</script> // OtherComponent.vue
<RichTextEditor v-model="myvalue" /> |
@nathanchase Yes there is, you just have the wrong prop name Replace :value="modelValue"
@input="$emit('update:modelValue', $event.target.value)" with :content="props.modelValue"
@update:content="$emit('update:modelValue', $event)" You may also need to do |
// RichTextEditor.client.vue
<template>
<div>
<div class="editor">
<QuillEditor
v-model:content="value"
content-type="html"
:options="defaultOptions"
:placeholder="placeholder"
theme="bubble"
@update:content="handleChange"
/>
</div>
</div>
</template>
<script setup lang="ts">
import '@vueup/vue-quill/dist/vue-quill.bubble.css';
import 'quill-paste-smart';
const props = defineProps({
modelValue: {
type: String,
default: '',
required: false,
},
placeholder: {
type: String,
default: '',
required: false,
},
});
const emit = defineEmits(['update:modelValue']);
const defaultOptions = ref({
theme: 'bubble',
modules: {
clipboard: {
allowed: {
tags: ['em', 'strong', 's', 'p', 'br', 'ul', 'ol', 'li', 'span'],
},
keepSelection: true,
},
toolbar: [
['bold', 'italic', 'strike'],
['blockquote'],
[{ list: 'ordered' }, { list: 'bullet' }],
['clean'],
],
},
});
const internalValue = ref();
const value = computed({
get(): string | null | undefined {
return props.modelValue;
},
set(newValue) {
internalValue.value = newValue;
emit('update:modelValue', newValue);
},
});
if (!process.server) {
const { QuillEditor } = await import('@vueup/vue-quill');
const { vueApp } = useNuxtApp();
if (!vueApp._context.components.QuillEditor) {
vueApp.component('QuillEditor', QuillEditor);
}
}
const handleChange = (value: any) => {
emit('update:modelValue', value);
};
</script> <LazyRichTextEditor
v-model:modelValue="htmlValue"
placeholder="Placeholder text"
/> |
There is no reason you need to introduce an intermediate reactive variable, that's a lot of redundant code
Your mistake was not using <template>
<div>
<div class="editor">
<QuillEditor
:content="props.modelValue"
content-type="html"
:options="defaultOptions"
:placeholder="placeholder"
theme="bubble"
@update:content="handleChange"
/>
</div>
</div>
</template>
<script setup lang="ts">
import '@vueup/vue-quill/dist/vue-quill.bubble.css';
import 'quill-paste-smart';
const props = defineProps({
modelValue: {
type: String,
default: '',
required: false,
},
placeholder: {
type: String,
default: '',
required: false,
},
});
const emit = defineEmits(['update:modelValue']);
const defaultOptions = ref({
theme: 'bubble',
modules: {
clipboard: {
allowed: {
tags: ['em', 'strong', 's', 'p', 'br', 'ul', 'ol', 'li', 'span'],
},
keepSelection: true,
},
toolbar: [
['bold', 'italic', 'strike'],
['blockquote'],
[{ list: 'ordered' }, { list: 'bullet' }],
['clean'],
],
},
});
if (!process.server) {
const { QuillEditor } = await import('@vueup/vue-quill');
const { vueApp } = useNuxtApp();
if (!vueApp._context.components.QuillEditor) {
vueApp.component('QuillEditor', QuillEditor);
}
}
const handleChange = (value: any) => {
emit('update:modelValue', value);
};
</script> |
@Tofandel Ok, this works and allows me to remove the computed property: <QuillEditor
:content="modelValue" // <- not 'props.modelValue', but just 'modelValue'
content-type="html" // <- this HAS to be html... if it's not, it throws a recursion error
:options="defaultOptions"
:placeholder="placeholder"
theme="bubble"
@update:content="handleChange"
/> Thanks for the help! |
@Tofandel thank you my brother!! I was about to abandon this component because the two-way binding was broken. |
Would thank anyone for a little help here as I try to get two-way binding working with vue-quill. I understand from the docs that v-model:content is the prop I need to use for two way binding. Here is my vue3 composition template in its simplest form:
So my intent is to bind the editor contents 2-way with selectedNote - the above appears to work but generates the following error in console "[Vue warn]: Maximum recursive updates exceeded." However - everything works as expected if I change my content-type to text or html. Is there a way to have error-free two-way binding whilst also using delta as my content type? |
Does the error still happens if you use |
Good shout mate worth a try - have just done so though and the behaviour is the same. Have also noticed that every keypress moves the cursor back to the start of the editor window again. Its not the end of the world if I have to use HTML, it just feels like using delta is a lot more elegant. |
As a workaround, try to create a delta with some content in it, there might be a bug in the previous PR for deltas as I'm not using it and the tests only cover a non empty delta, I'll investigate |
Okay Tofandel, thank you again - have just tried that, I took a snippet from the demo folder on the repo, so the delta I made looks like this:
And the result was the same - but it brought me to trying to run the demos from the repo - and indeed when I do that, they produce the same error result; they too are two-way binding a delta object with v-model:content. I checked a different browser just to be sure and the behaviour was the same on Chrome and on Safari. |
I've found the issue, it was a small one, I'll make a follow up PR |
Woo that’s mega, thank you Tofandel, giving your change a try 🙏 |
Have pulled your repo + built mate, with mixed results. Firstly, the errors are gone. When you change the content of the quilleditor, changes are pushed back to the property as I'd expect. However, though the quilleditor component always reflects the initial value of its bound property, if I subsequently change the value of the bound property with delta manipulation. the editor doesn't reflect the change, for example:
or indeed straight up replacing the delta entirely:
The editor doesn't pick these up - its only two way binding at moment of initial population, after that its 1-way only. Here is a minimal example to demonstrate, which changes the bound property to no effect:
Would again appreciate your thoughts, thank you for bearing with! |
@adrianhand Are you sure you're on the correct branch if you pulled the fork? Because the pen is exactly as in the demo, which works fine, but for the |
Ahhhhh mate I am so so sorry, when I pulled I assumed I would default to tofandel/master - I am sure switching to the right branch will do the trick, I am ashamed. Will follow up with a result. |
It is in fact master, I added deep reactivity support for delta, give it a pull and let me know |
Okay bud, you were absolutely right - sorry again(!) - I was not using your master branch. When checkout correctly everything works as expected with error-free two-way binding between v-model:content and my objects. However (!) whilst every text change is reflected in my object, some operations like setting text style aren't pushed through to the model object. If I subsequently make a text change, reactivity forces the binding to refresh and my text styles are there in the delta. Its a really little thing and I don't know what I can reasonably expect here. |
Indeed, gave it a try and also pushed a fix for that as well |
🎉 This issue has been resolved in version 1.1.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
Why use such a plugin that complicates the work? He just needs to link v-model and that's it. |
This still doesn't work as it should. I have a case, where I have multiple text editors spawned in a for loop. And when I insert one in the middle with an empty model value (''), and the component which renders the editor updates, the texteditor still has the text from the previous model value inside. If I insert one in the middle, which HAS a model value (eg. '.'), it works as expected. It seems there is a problem when the model value was set to an empty string, that doesn't update the text you see on the screen. But the content value of the editor updates just fine. |
@cortnum Are you using 1.1.0? 1.0.1 had the issue you describe, which has been fixed Please provide a reproduction using codepen or codesandbox |
@Tofandel yes I am. I will try to make one later today |
`<script setup name="QuillEditor"> if (!Quill.imports["modules/BlotFormatter"]) { const props = defineProps({ // 定义content为响应式对象 还是十六客服的杀骷髅反对吧打死了几分 杀骷髅反对吧打死了几分 `);const toolbar = ref([ const myQuillEditor = ref(null) </script> ` The data cannot be rendered, and when the component passes in the data, it seems to have been rendered to the editor, but the editor automatically replaces all of them with empty labels |
You need to choose one type, you can't pass multiple like this |
v-model:content not working when changed the binding value, it seems not two way binding,
@feature
The text was updated successfully, but these errors were encountered: