Search code examples
vue.jshidden-field

VueJS - how can I add a hidden input to a form?


I created a Vue component that has several forms that can be submitted by the user. On submit, the form will send some data to my backend. The problem is that my backend needs to know which form was submitted, and this input doesn't depend on the user, so I added a hidden input so that when the user send the data, my backend can also know which type of form was submitted. I tried the following:

<template>
  <div>
      
      <div v-if="order=='total'">

        <form @submit="formSubmit">

        <input type="hidden" v-model="order_type" value="form1">

        <input type="text" class="form-control" v-model="amount">
        <br>
        <input type="text" class="form-control" v-model="price">
        <br>

        <button class="btn btn-primary">BUY</button>

        </form>

      </div>

      <div v-else-if="order=='partial'">

        <input type="hidden" v-model="order_type" value="form2">

        <input type="text" class="form-control" v-model="amount">
        <br>
        <input type="text" class="form-control" v-model="price">
        <br>

        <button class="btn btn-primary">BUY</button>

        </form>

      </div>

      <br>

  </div>

</template>
     
<script>

import axios from 'axios'

    export default {

      props:{

        order:{
          type:String, 
          default:'total'
        },

      },

      mounted() {
          console.log('Component mounted.')
      },

      data() {
          return {
            name: '',
            description: '',
            output: ''
          };
      },
      methods: {
          formSubmit(e) {
              e.preventDefault();
              let currentObj = this;
              axios.post('MYURL', {
                  order_type: this.order_type,
                  price: this.price,
                  amount: this.amount
              })
              .then(function (response) {
                  currentObj.output = response.data;
              })
              .catch(function (error) {
                  currentObj.output = error;
              });
          }
      }
    }

</script>

The problem with this code is that order_type doesn't get sent with the form. I have read somewhere that Vue doesn't allow hidden values, so is there any other way to do this?


Solution

  • You can pass a param to the method:

    @submit.prevent="formSubmit("form1")"
    

    And in the method:

    formSubmit(value) {
      let currentObj = this;
      axios
        .post("MYURL", {
          price: this.price,
          amount: this.amount,
          order_type: value
        })
        .then(function(response) {
          currentObj.output = response.data;
        })
        .catch(function(error) {
          currentObj.output = error;
        });
    },
    

    Your template becomes:

    <template>
      <div>
          <div v-if="order=='total'">
            <form @submit.prevent="formSubmit("form1")">
            <input type="text" class="form-control" v-model="amount">
            <br>
            <input type="text" class="form-control" v-model="price">
            <br>
            <button class="btn btn-primary" type="submit">BUY</button>
            </form>
          </div>
          <div v-else-if="order=='partial'">
            <form @submit.prevent="formSubmit("form2")">
            <input type="text" class="form-control" v-model="amount">
            <br>
            <input type="text" class="form-control" v-model="price">
            <br>
            <button class="btn btn-primary" type="submit">BUY</button>
            </form>
          </div>
          <br>
      </div>
    </template>
    

    SOLUTION 2 To avoid duplication you could also set a computed property:

    orderType(){
      if (this.order === "total") {
        return "form1"
      } else if (this.order === "partial") {
        return "form2"
      } else {
        return null
    }
    

    With that in place you can simplify the template by removing the conditional and not needing to pass anything to the method:

    <template>
      <div>
        <form @submit.prevent="formSubmit()">
          <input type="text" class="form-control" v-model="amount" />
          <br />
          <input type="text" class="form-control" v-model="price" />
          <br />
          <button class="btn btn-primary" type="submit">BUY</button>
        </form>
      </div>
    </template>
    

    And in the method the value of order_type is calculated in the computed property:

       formSubmit() {
          let currentObj = this;
          axios
            .post("MYURL", {
              price: this.price,
              amount: this.amount,
              order_type: this.orderType
            })
            .then(function(response) {
              currentObj.output = response.data;
            })
            .catch(function(error) {
              currentObj.output = error;
            });
        },