Reputation: 5106
I have three Vue components: FormField.vue, GenericForm.vue (contains FormField
) and SignupPage.vue (contains GenericForm
)
The GenericForm.vue has a inputFunction prop which is a function that is passed to it by a child component. It gets executed on button click.
The SignupPage.vue has a function register which sends a post request to a certain endpoint.
I need to somehow get the data of the fields from the fields in the GenericForm.vue so that that data gets sent when the button is clicked when inside SignupPage.vue component.
GenericForm.vue:
<template>
<form v-on:submit.prevent="execute()"
class="signup-form rounded-lg
p-10 m-auto align-middle content-center
space-y-6
flex flex-col items-center justify-center
">
<div class="title-text light-text text-xl">Signup</div>
<FormField v-for="(field) in fields"
v-bind:key="field" :placeholder="field"
/>
<GenericButton :text="buttonText"/>
</form>
</template>
export default {
components: {GenericButton, FormField, ArticleList},
props: {
title: {
type: String,
required: true
},
fields: {
type: Array,
required: true
},
buttonText: {
type: String,
required: true
},
inputFunction: {
type: Function
}
},
...
...
methods: {
execute() {
console.log("GenericForm.vue")
if (this.inputFunction) {
this.inputFunction()
}
},
}
...
FormField.vue:
<template>
<input :placeholder= "placeholder"
class = " form-field
p-2 pl-0 pt-4 pb-2 w-1/3 "
/>
</template>
<script>
export default {
props: ['placeholder']
}
</script>
SignupPage.vue:
<template>
<div class=" ">
<GenericForm title = "Sign Up" button-text= "Sign Up"
:fields="['Username', 'Email', 'Password']"
:inputFunction = "register"
/>
</div>
</template>
...
methods: {
async register() {
console.log("register()")
const response = AuthenticationService.register({
email: 'wwwwww',
password: 'frgr'
}).then((response) => {
console.log(response)
console.log(this.$store)
this.$router.push({
name: 'ha'
})
});
}
}
...
Upvotes: 0
Views: 134
Reputation: 138336
For this, I would name the input
s, and use new FormData()
on the <form>
element, which would automatically collect all named fields anywhere in the form (even deep nested ones).
In GenericForm.vue
, update the v-on:submit
value from execute()
to execute
(just the method name), so that the submit
-event data is automatically passed to the handler. We'll use this event data to get the form. Also bind <FormField>.name
to each field
.
<template>
<form v-on:submit.prevent="execute">
<FormField v-for="(field) in fields" :name="field" />
</form>
</template>
Update execute()
to receive the event data, create the FormData
from it, and pass the result as an argument to inputFunction()
:
execute(e) {
const form = e.target
const formData = new FormData(form)
if (this.inputFunction) {
this.inputFunction(formData)
}
}
In SignupPage.vue
, update register
to receive the form data:
async register(formData) {
const email = formData.get('Email')
const password = formData.get('Password')
//...
}
Upvotes: 1
Reputation: 303
you can use reference by path in js objects for sync data in vue like that:
SignupPage.vue:
data: {
formData: {}
}
<GenericForm :formData="formData" :fields="['Username', 'Email', 'Password']" />
GenericForm.vue:
props: ['formData']
<FormField v-for="(field) in fields" v-bind:key="field" :field="field" :formData="formData" />
FormField.vue:
props: ['formData', 'field']
<input type="text" v-model="formData[field]" />
then you have synced form data in formData Object in signupPage.vue
Upvotes: 1