Luiz Alves
Luiz Alves

Reputation: 2645

Make a reactive component with vuejs

I need a Vue component to show some HTML content in v-data-table from Vuetify. I have seen this post Vue 2 contentEditable with v-model, and I created a similar code shown below.

My problem is the component is not reactive. When I click the "Test button", no content is updated in HtmlTextArea.

<template>
    <div>
      <v-btn @click="doTest()">Test Button</v-btn>
      <HtmlTextArea
        v-model="content"
        style="max-height:50px;overflow-y: scroll;"
      ></HtmlTextArea>
    </div>
<template>

export default {
  name: "ModelosAtestados",
  components: { HtmlTextArea },
  data: () => ({
    content: "",
  }),
  methods: {
    doTest() {
      this.content = "kjsadlkjkasfdkjdsjkl";
    },
  },
};


//component
<template>
  <div ref="editable" contenteditable="false" v-on="listeners"></div>
</template>

<script>
export default {
  name: "HtmlTextArea",
  props: {
    value: {
      type: String,
      default: "",
    },
  },
  computed: {
    listeners() {
      return { ...this.$listeners, input: this.onInput };
    },
  },
  mounted() {
    this.$refs.editable.innerHTML = this.value;
  },
  methods: {
    onInput(e) {
      this.$emit("input", e.target.innerHTML);
    },
  },
};
</script>

Upvotes: 0

Views: 376

Answers (2)

tony19
tony19

Reputation: 138216

This occurs because HtmlTextArea sets the div contents to its value prop only in the mounted lifecycle hook, which is not reactive.

The fix is to setup a watcher on value, so that the div contents are updated to match whenever a change occurs:

// HtmlTextArea.vue
export default {
  watch: {
    value: {
      handler(value) {
        this.$refs.editable.innerHTML = value;
      }
    }
  }
}

demo

Upvotes: 1

Kapcash
Kapcash

Reputation: 6909

In the @click event binder, you have to pass a function. You passed the result of an executed function.

To make it work: @click="doTest" or @click="() => doTest()".

How to debug such problems:

  • Display the value you want to update on your template to check if its updated: {{content}}
  • Use the vue devtool extension to check the current state of your components

Upvotes: 0

Related Questions