I'm using Nuxt and Netlify Forms for a contact form, Everything is working as expected (validation, submit success) however I am getting empty form fields on submissions. I have tried matching the v-model and form names with no success. Do I have to change the body.encode to retrieve the v-model fields or somehow get the value of the name fields inputs?
Markup:
<form
name="contactForm"
method="post"
netlify-honeypot="bot-field"
data-netlify="true"
@submit.prevent="handleSubmit()"
>
<input type="hidden" name="form-name" value="contactForm" />
<div class="form-group">
<!--user name -->
<div class="floating-label">
<input
v-model="contact_name"
class="floating-input"
name="name"
type="text"
placeholder=" "
:class="{
'child-has-error': $v.contact_name.$error,
}"
/>
<label>Enter Your Name</label>
<p v-if="$v.contact_name.$dirty">
<span
v-if="!$v.contact_name.required"
class="form__alert"
>
Name is required
</span>
</p>
</div>
<!-- end user name -->
<!--user email -->
<div class="floating-label">
<input
v-model="contact_email"
class="floating-input"
type="text"
name="email"
placeholder=" "
:class="{
'child-has-error': $v.contact_email.$error,
}"
/>
<label>Enter Your Email</label>
<p v-if="$v.contact_email.$dirty">
<span
v-if="!$v.contact_email.required"
class="form__alert"
>
Email is required
</span>
<span v-if="!$v.contact_email.email" class="form__alert">
Please enter a valid email
</span>
</p>
</div>
<!-- end user email -->
<!--user message -->
<div class="floating-label">
<textarea
v-model="contact_message"
class="form-control form-control--textarea"
rows="5"
name="message"
placeholder="Enter Your Message"
:class="{ 'child-has-error': $v.contact_message.$error }"
/>
<p v-if="$v.contact_message.$dirty">
<span
v-if="!$v.contact_message.required"
class="form__alert"
>
Enter Your Message
</span>
<span
v-if="!$v.contact_message.minLength"
class="form__alert"
>
Message must be over 10 characters :)
</span>
</p>
</div>
<!-- end user message -->
</div>
<button type="submit" class="btn btn-primary">
Send Message
<font-awesome-icon far icon="arrow-right" />
</button>
</form>
Script:
<script>
import { required, email, minLength } from 'vuelidate/lib/validators'
export default {
data() {
return {
title: 'Contact Form',
show_contact: true,
contact_name: '',
contact_email: '',
contact_message: '',
form: {
name: '',
email: '',
message: '',
},
}
},
validations: {
contact_name: {
required,
},
contact_email: {
required,
email,
},
contact_message: {
required,
minLength: minLength(10),
},
},
methods: {
encode(data) {
return Object.keys(data)
.map(
(key) => `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`
)
.join('&')
},
handleSubmit() {
this.$v.$touch()
if (this.$v.$invalid) {
return true
}
fetch('/', {
method: 'post',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: this.encode({
'form-name': 'contactForm',
...this.form,
}),
})
// eslint-disable-next-line no-console
.then(() => {
this.show_contact = false
// eslint-disable-next-line no-console
console.log('Message Success')
})
// eslint-disable-next-line no-console
.catch((e) => console.error(e))
},
},
}
</script>
You've been sending this.form
as your data
body: this.encode({
'form-name': 'contactForm',
...this.form,
}),
but you never set values to it based on your inputs. I did not see any reference to it.
Either use those in your v-model bindings or convert this.form
from data to a computed property like:
form() {
return {
name: this.contact_name,
email: this.contact_email,
message: this.contact_message
}
}