Search code examples
vue.jsvuejs2vuex

Submit values from multiple components


I am using vuejs-wizard to create registration page, I have each tab in component like this

<form-wizard color="#fcab1a" title="" subtitle="" finish-button-text="Register">
  <tab-content title="Personal Info" icon="icon-location3 fa-2x">
    <personal-info></personal-info>
  </tab-content>
  <tab-content title="Contact Info" icon="icon-box fa-2x">
    <contact-info></contact-info>
  </tab-content>
  <tab-content title="Address" icon="icon-alarm fa-2x">
    <address></address>
  </tab-content>
</form-wizard>

personal info:

<template>
  <div class="card">
    <div class="card-header">
      <h5 class="card-title">Personal Info</h5>
    </div>
    <div class="card-body">
      <div class="form-group">
        <div class="row">
          <div class="col-md-6">
            <label>Full Name <span class="text-danger">*</span></label>
            <input type="text" value="" class="form-control" v-model="name" />
          </div>
        </div>
      </div>
      <div class="form-group">
        <div class="row">
          <div class="col-md-6">
            <label>Age <span class="text-danger">*</span></label>
            <input type="number" value="" class="form-control" v-model="age" />
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

contact info:

<template>
  <div class="card">
    <div class="card-header">
      <h5 class="card-title">Contact Info</h5>
    </div>
    <div class="card-body">
      <div class="form-group">
        <div class="row">
          <div class="col-md-6">
            <label>Mobile <span class="text-danger">*</span></label>
            <input type="text" value="" class="form-control" v-model="mobile" />
          </div>
        </div>
      </div>
      <div class="form-group">
        <div class="row">
          <div class="col-md-6">
            <label>Email <span class="text-danger">*</span></label>
            <input
              type="number"
              value=""
              class="form-control"
              v-model="email"
            />
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

so my question is, what is the best way to submit the form, do I need vuex to store the state or is there a better/easier way ?

Thanks


Solution

  • It depends...

    The answer depends on various factors. For example, are you using vuex already, size of the app, test-ability of app, and even how are fields get validated (asynch/api validations?).

    When it's a simple app, and I only have direct parent=>child relationships, I tend to skip adding the Vuex as a dependency. (but I mostly deal with SPAs, so I usually use it) YMMV.

    In this case, that would require that the fields are defined in the parent. Then adding props and emitters for each value to the children, and a listener on the parent. As you start to add more fields though, you might find this tedious, and opt to pass fields in an object either in groups, or as whole (and only pick the ones you need in tab), and then you can implement your own v-model in the tab components which can make it pretty easy to pass the object around

    If you're using a more recent Vue version (2.6+), you could use vue.observable to share a store between multiple components without the bells/whistles of Vuex

    There's a good article that shows how to build a vuex clone with it, but in reality it's much, much simpler than that to create a store that would suit your needs. Let me know in the comments if you're interested in how to implement it, and I can describe it.


    Rolling with custom store

    it's really as simple as this

    Create a store.js file with...

    import Vue from 'vue';
    
    const store = Vue.observable({
      name: null,
      email: null,
      age: null,
      mobile: null,
    });
    
    export default store;
    

    then in any component that you want to have access to it, add the store during create

    import store from "../store";
    
    export default {
      name: "PersonalInfo",
      created() {
        this.$store = store;
      }
    };
    

    now the all the store is available to you in the template through $store

    <input type="text" value class="form-control" v-model="$store.name">
    

    codesandbox example

    You lose the benefits, such as "time-traveling" over mutations that Vuex offers. Because you're not dealing with the scale that the flux pattern (vuex) was meant for, I would use this solution in an app this size.