Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How To Create a Reusable Form Vue Component

Tags:

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.

AddressComponent.vue

<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>

ContactForm.vue

<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>
like image 297
RobDiablo Avatar asked Mar 15 '18 19:03

RobDiablo


People also ask

How do I make reusable components Vue?

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.

How do I create a custom component on Vue?

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.

How do I force a component to reload in Vue?

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.


1 Answers

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>
like image 80
Lawrence Cherone Avatar answered Nov 15 '22 03:11

Lawrence Cherone