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?

+3


source to share


1 answer


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/

+1


source







All Articles