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();:value="myData"/ v-model="myData" on inputsand 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?
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();
});
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,
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With