vue submit form with updated input values

9.9k views Asked by At

I have a simple hidden form

<template>
  <form ref="form" method="POST" action="https://target.com/post" accept-charset="utf-8">
    <input type="hidden" name="data" :value="myData"/>
    <input type="hidden" name="signature" v-model="mySignature" />
    <input ref="submit" type="submit">
  </form>
</template>

and I want my method which is attached to different button (v-on:click="submitForm")to submit this form setting the data.

export default {
  name: 'MyComponent',
  methods: {
    submitForm() {
      // should update values for inputs
      this.myData = 'dynamically calculated';
      this.mySignature = 'creates signature from data';
      // submit the form with values above
      this.$refs.form.submit();
    },
  },
  data() {
    return {
      myData: null,
      mySignature: null,
    }
  }
}

But seems like I misunderstand reactivity/binding/refs? in Vue, so I've tried

  • this.$refs.submit.click();
  • this.$forceUpdate();
  • setting :value="myData"/ v-model="myData" on inputs

and none of the methods work. Form got sent with empty fields for data/signature, so it seems like variables are not updated or form is not able to rerender within one function call. What's the proper way of doing such an update?

3

There are 3 answers

0
Winns On BEST ANSWER

Vue performs DOM updates asynchronously. In your case DOM update does not happen before form submit.

Workaround is to use $nextTick

this.$nextTick(() => {
    this.$refs.form.submit();
});
0
Daniel On

It looks like an issue with <form> and not reactivity.

You have defined a <form> element with an action action="https://target.com/post". This tells the browser to handle your form and will ignore any of the javascript handling. When the user clicks on <input ref="submit" type="submit">

If you are building an SPA, you should probably just remove the form element and handle the submit with an ajax call. This will make handling of the form interaction much more consistent, but you'll lose the no-js-enabled fallback functionality, however, given that it is a hidden form triggered by js, that may not be an issue anyway.

Anyhow, if you want to handle it with a form element, you can add an @submit event handler, with a e.preventDefault() in the handler to prevent the form submitting if the conditions are not matched. Be sure to test on multiple browsers, since there was some inconsistency around the handling of form submit functionality between chrome and firefox.

<template>
  <form ref="form" method="POST" action="https://target.com/post" accept-charset="utf-8" @submit="handleSubmitForm">
    <input type="hidden" name="data" :value="myData"/>
    <input type="hidden" name="signature" v-model="mySignature" />
    <input ref="submit" type="submit">
  </form>
</template>
export default {
  name: 'MyComponent',
  methods: {
    submitForm() {
      // should update values for inputs
      this.myData = 'dynamically calculated';
      this.mySignature = 'creates signature from data';
      // submit the form with values above
      this.$refs.form.submit();
    },
    handleSubmitForm(e) {
      if (this.myData !== "what I want") {
        e.preventDefault();  // prevent form submit
      }
    },
  },
  data() {
    return {
      myData: null,
      mySignature: null,
    }
  }
}
0
Phil On

I met the same issue and found the follow solution:

this.myData = 'dynamically calculated';
this.mySignature = 'creates signature from data';

//force to update form
this.$refs.form.data = this.myData;
this.$refs.form.signature = this.mySignature;

// submit the form with values above
this.$refs.form.submit();

However, the nextTick approach is better.