Home > front end >  Form component in Vue fires submit event twice
Form component in Vue fires submit event twice

Time:10-08

I'm using the latest version of Vue 3, with no other vendors.

It may be a bug, or it is an expected behaviour, but I lost a couple of hours finding why my form component was firing the submit event twice.

It fact, if you listen to @submit on your form, and then $emit('submit') so you can listen to this event on the parent component, the event will be fired twice.

More than words, here is a pen to show this: https://codepen.io/rekam/pen/dyeqxyy

const { createApp } = Vue

const TestForm = {
  template: `
    <form @submit.prevent.stop="onSubmit">
      <input type="text" />
      <input type="submit" value="in component" />
    </form>
  `,
  props: {
    eventName: { type: String }
  },
  methods: {
    onSubmit() {
      this.$emit(this.eventName)
    }
  }
}

createApp({
  template: `
    <div>
      <TestForm event-name="submit" @submit="() => onSubmit('with event name [submit]')" />
      <TestForm event-name="other" @other="() => onSubmit('with event name [other]')" />
      <blockquote>
        <p v-for="(log, i) in logs" :key="i">{{ log }}</p>
      </blockquote>
      <input type="button" value="clear" @click="logs = []" />
    </div>
  `,
  components: { TestForm },
  data: () => ({
    logs: []
  }),
  methods: {
    onSubmit(msg) {
      console.log(msg)
      this.logs.push(msg)
    }
  }
}).mount('#app')

I can live with that, I just need to give a specific name to my own submit event. My question is: why is this happening and is it expected?

EDIT

I just found that wrapping the form tag in a div get rid of the second submit event. To have the submit event fired twice, you need:

  1. your form beign the top level dom element in your component
  2. emit an event named "submit"

CodePudding user response:

you call submit twice with an eventlistener you created from emit and another from @submit you added to your form tag. you should use one of them to submit your form.

CodePudding user response:

You dont need to add the event @submit.prevent.stop="onSubmit" in you're child component because it will be inherited from the parent component';

template: `
    <form>
      <input type="text" />
      <input type="submit" value="in component" />
    </form>
  `,

template: `
    <div>
      <TestForm event-name="submit" @submit.prevent="() => onSubmit('with event name [submit]')" />
      <TestForm event-name="other" @submit.prevent="() => onSubmit('with event name [other]')" />
      <blockquote>
        <p v-for="(log, i) in logs" :key="i">{{ log }}</p>
      </blockquote>
      <input type="button" value="clear" @click="logs = []" />
    </div>
  `,

https://codepen.io/keyXpert/pen/dyegYQB

  • Related