Let's say I want to create a contact form. In this contact form, a user can have multiple addresses. I would think that this is a perfect opportunity to use a Vue Component so that I don't have to create redundant address form fields. I would then be able to use this component in different areas of a website, say on edit, create, etc....
How would I go about creating a form component that a parent can use and have values from that form get added to an addresses array? Also, I would like to be able to populate this form with existing values if it's being edited.
I've tried different things but nothing I've tried seems to work. Any ideas? I've searched Stack and Google but haven't been able to find an answer.
Here is some starting code of what I'm trying to accomplish (crude example). Of course, I would allow a user to dynamically add multiple addresses on creation/edit but I would also on edit of the form loop through the addresses data to display each address component but this is just a quick non-working setup to get my point across.
<template>
<div>
<h4>Address</h4>
<label>Address</label>
<input type="text" v-model="address">
<label>City</label>
<input type="text" v-model="city">
<label>State</label>
<input type="text" v-model="state">
</div>
</template>
<script>
export default {
data() {
return {
address: null,
city: null,
state: null
}
}
}
</script>
<template>
<h1>My Contact Form</h1>
<form>
<AddressComponent></AddressComponent> // Addresses[0]
<AddressComponent></AddressComponent> // Addresses[1]
</form>
</template>
<script>
import AddressComponent from '../components/AddressComponent'
export default {
components: {AddressComponent},
data() {
return {
addresses: [],
}
}
}
</script>
Each component you create in your Vue app should be registered so Vue knows where to locate its implementation when it is encountered in a template. To register your component in another component, you should add it to the components property in the Vue object.
Open the file in your code editor. Create the component's template section by adding <template></template> to the top of the file. Create a <script></script> section below your template section. Inside the <script> tags, add a default exported object export default {} , which is your component object.
The best way to force Vue to re-render a component is to set a :key on the component. When you need the component to be re-rendered, you just change the value of the key and Vue will re-render the component.
Perhaps something like this, pass in the data and then emit the change back to the parent.
Vue.component('address-component', {
template: '#address',
props: ['data', 'index'],
data() {
return {
item: {
address: this.data.address,
city: this.data.city,
state: this.data.state
}
}
},
methods: {
inputOccurred() {
this.$emit('on-change', this.item, this.index)
}
}
});
//
var vm = new Vue({
el: '#app',
data() {
return {
addresses: [{
address: '1 Stackoverflow Way',
city: 'San Fran',
state: 'California'
},
{
address: '2 Stackoverflow Way',
city: 'San Fran',
state: 'California'
}
]
}
},
methods: {
setAddress(value, index) {
this.$set(this.addresses, index, value);
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.14/vue.min.js"></script>
<div id="app">
<h1>My Contact Form</h1>
<address-component
v-for="(address, index) in addresses"
:data="address"
:index="index"
:key="index"
@on-change="setAddress"
></address-component>
<pre>{{ addresses }}</pre>
</div>
<template id="address">
<div>
<h4>Address</h4>
<label>Address</label>
<input type="text" v-model="item.address" @input="inputOccurred"/>
<label>City</label>
<input type="text" v-model="item.city" @input="inputOccurred"/>
<label>State</label>
<input type="text" v-model="item.state" @input="inputOccurred"/>
</div>
</template>
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