Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue model not updating

Tags:

vue.js

vuejs2

When I try to update my custom text-area component's model data this.message='<span id="foo">bar</span> the text and html does not display in the htmltextarea tag like it should, but I can see the update applied in the Vue dev tool's console. I've also tried switching to an object instead of a string and using Vue.set, but this does not work either.

Any suggestions on how to fix this?

The goal with the htmlTextArea component is to get the users text from the htmlTextArea tag (this works), manipulate this text and bind it back to the textarea, but with HTML in it.

Custom text-area component:

<template>
  <div contenteditable="true" @input="updateHTML" class="textareaRoot"></div>
</template>
<script>
export default {
  // Custom textarea 
  name: 'htmlTextArea',
  props:['value'],
  mounted: function () {
      this.$el.innerHTML = this.value;
  },
  methods: {
      updateHTML: function(e) {
          this.$emit('input', e.target.innerHTML);
      }
  }
}
</script>

Other component:

<template>
...
<htmlTextArea id="textarea" v-model="message"></htmlTextArea>
...
</template>
<script>
      data: {
        return {
          message: 'something'//this works
        }
      }
     ...
     methods: {
      changeText() {
        this.message='<span id="foo">bar</span>'//this does not
      }
     },
     components: {
         htmlTextArea
     }
</script>
like image 966
now_world Avatar asked Apr 13 '18 04:04

now_world


People also ask

Does Vue automatically update?

One of Vue's best features is reactivity. You change a variable, and Vue automatically updates what is rendered to the page. However, not everything in Vue is reactive by default.

How do I Rerender components in Vue?

The best way to force Vue to re-render a component is to set a :key on the component. When you need the component to be re-rendered, you just change the value of the key and Vue will re-render the component.

What is the difference between V model and V bind?

v-model is for two way bindings means: if you change input value, the bound data will be changed and vice versa. But v-bind:value is called one way binding that means: you can change input value by changing bound data but you can't change bound data by changing input value through the element.


2 Answers

You need to set the value explicitly after the value props change. you can watch for value change.

<template>
    <div contenteditable="true" @input="updateHTML" class="textareaRoot"></div>
</template>
<script>

export default {
  // Custom textarea
  name: "htmlTextArea",
  props: ["value"],
  mounted: function() {
    this.$el.innerHTML = this.value;
  },
  watch: {
      value(v) {
          this.$el.innerHTML = v;
      }
  },
  methods: {
    updateHTML: function(e) {
      this.$emit("input", e.target.innerHTML);
    }
  }
};
</script>
like image 180
Jacob Goh Avatar answered Sep 20 '22 16:09

Jacob Goh


Change the data property into a function, as you have it defined it is not reactive.

data () {
    return {
        message: 'something'//this works 
    }
}

Now when you update the message property in your method, the component will update accordingly.

Reactivity in depth

like image 22
Brian Lee Avatar answered Sep 23 '22 16:09

Brian Lee