Amar
Amar

Reputation: 529

$emit executes before computed

I'm trying to emit a prop that I modify. I can do that directly with the prop and it works but I get a Vue Warn: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders

So I tried to put the prop in a computed, but the emit executes before the computed is executed.

template:
          <input
                v-on:keyup="validatedate(localDate)"
                v-on:change="emitAnswer(localDate)"
                v-model="localDate">
 ,
 computed: {
    dateLocal: {
        get: function () {
            return this.date
        }
 }
 methods: {
     emitAnswer: function (date) {
        this.$emit('myFunc', date);
    }
 }

Upvotes: 1

Views: 3727

Answers (3)

Sovalina
Sovalina

Reputation: 5609

To avoid mutating a prop, it’s best to define a local data property that uses the prop as its initial value (source):

props: ['date'],
data () {
  return {
    localDate: this.date
  }
}

Now you can use the localDate data as v-model and you don't need any parameter for your emitAnswer method:

//template
  <input @change="emitAnswer" v-model="localDate">

//script
props: ['date'],
data () {
  return {
    localDate: this.date
  }
},
methods: {
  emitAnswer () {
    this.$emit('myFunc', this.localDate)
  }
}

Upvotes: 0

Ignas Damunskis
Ignas Damunskis

Reputation: 1504

Firstly, I believe your computed is named wrongly ("dateLocal" should be "localDate"), but I thing that is not the problem.

Why don´t you check inside method right before emit if value is set?

methods: {
    emitAnswer: function (date) {
        if (date) {
            this.$emit('myFunc', date)
        }
    }
}

Also, for better practise, you should use sethandler for computed property you are about to modify:

 computed: {
     localDate: {
         get () {
             return this.date
         },
         set (date) {
             if (date) {
                 this.$emit('myFunc', date)
             }
         }
     }
 }

Hopefully this helps you, feel free to respond if you need further help.

Upvotes: 1

Marcelo
Marcelo

Reputation: 2524

Since Vue can't guarantee that v-model will be executed before the v-on:change, you can use watchers to only call the emit once the value of the property has been changed in the component, example:

watch {
  date() {
     this.$emit('myFunc', this.date)
  }
}

Upvotes: 5

Related Questions