VueJs: binding Textarea input
I am trying to figure out how to detect a change in value in a textbox inside a component.
For input, we can simply use
<input
:value="value"
@input="update($event.target.value)"
>
However, this won't work on textarea.
What I am working with is a CKEditor component that should update the wysiwyg content when the model value of the parent component (attached to that child component) is updated.
Currently my component Editor
looks like this:
<template>
<div class="editor" :class="groupCss">
<textarea :id="id" v-model="input"></textarea>
</div>
</template>
<script>
export default {
props: {
value: {
type: String,
default: ''
},
id: {
type: String,
required: false,
default: 'editor'
}
},
data() {
return {
input: this.$slots.default ? this.$slots.default[0].text : '',
config: {
...
}
}
},
watch: {
input(value) {
this.update(value);
}
},
methods: {
update(value) {
CKEDITOR.instances[this.id].setData(value);
},
fire(value) {
this.$emit('input', value);
}
},
mounted () {
CKEDITOR.replace(this.id, this.config);
CKEDITOR.instances[this.id].setData(this.input);
this.fire(this.input);
CKEDITOR.instances[this.id].on('change', () => {
this.fire(CKEDITOR.instances[this.id].getData());
});
},
destroyed () {
if (CKEDITOR.instances[this.id]) {
CKEDITOR.instances[this.id].destroy()
}
}
}
</script>
and I include it in the parent component
<html-editor
v-model="fields.body"
id="body"
></html-editor>
however, whenever the parent component's model value changes - it doesn't start the observer - it doesn't effectively refresh the editor window.
I only need a method update()
that gets called when the parent component's model is updated fields.body
.
Any pointer as to how I can approach it?
source to share
This is a fair bit of code to decode, but what I would like to do is split the text area and HTML WYSIWYG window into two different components, and then parent sync the values, so:
TextArea component:
<template id="editor">
<textarea :value="value" @input="$emit('input', $event.target.value)" rows="10" cols="50"></textarea>
</template>
/**
* Editor TextArea
*/
Vue.component('editor', {
template: '#editor',
props: {
value: {
default: '',
type: String
}
}
});
Everything I am doing here is returning the original to the parent object, when it changes, I use the input as the event name and value
as a prop so I can use v-model
in the editor. Now I just need a wysiwyg window to show the code:
WYSIWYG window:
/**
* WYSIWYG window
*/
Vue.component('wysiwyg', {
template: `<div v-html="html"></div>`,
props: {
html: {
default: '',
type: String
}
}
});
There is nothing special about this, it just passes the HTML that is passed in as a prop.
Finally, I just need to sync the values ββbetween components:
<div id="app">
<wysiwyg :html="value"></wysiwyg>
<editor v-model="value"></editor>
</div>
new Vue({
el: '#app',
data: {
value: '<b>Hello World</b>'
}
})
Now when the editor changes, it returns an event to the parent, which updates value
and, in turn, triggers that change in the wysiwyg window. Everything in action here: https://jsfiddle.net/Lnpmbpcr/
source to share