0

I have v-for form-group components i iterated over a select's value(integer). I want to get the values of the iterated v-models, but i just can't seem to get it right

TEMPLATE
      <b-form-group
        id="input-group-1"
        label="Jumlah Lowongan:"
        label-for="selectJumlahLow"
        description="Silahkan pilih satu."
        v-if="show"
      >
        <b-form-select id="selectJumlahLow" v-model="form.jumlahlow" :options="selow" required></b-form-select>
      </b-form-group>

      <b-form-group label="Nama Lowongan:" v-for="n in parseInt(form.jumlahlow)" :key="n">
        <b-form-input required placeholder="Masukkan nama lowongan" v-model="low"></b-form-input>
      </b-form-group>
SCRIPT DATA
   data() {
    return {
      form: {
        jumlahlow: 1,
        checked: [],
        low: []
      } 
    }

I've tried changing the model to low[n] or declaring low in data as object {} but either of these seems to be undefined according to TypeErrors i've encoutered.

How am i suppose to get the low[n]'s values?

EDIT:

Here is the full code:

<template>
  <div>
    <b-form @submit="onSubmit" @reset="onReset">
      <b-form-group
        id="input-group-1"
        label="Jumlah Lowongan:"
        label-for="selectJumlahLow"
        description="Silahkan pilih satu."
        v-if="show"
      >
        <b-form-select id="selectJumlahLow" v-model="form.jumlahlow" :options="selow" required></b-form-select>
      </b-form-group>

      <b-form-group label="Nama Lowongan:" v-for="n in parseInt(form.jumlahlow)" :key="n">
        <b-form-input required placeholder="Masukkan nama lowongan" v-model="low"></b-form-input>
      </b-form-group>

      <b-button type="submit" variant="primary">
        {{ buttonText }}&nbsp;
        <i class="material-icons">arrow_forward_ios</i>
      </b-button>
      <b-button type="reset" variant="danger">Reset</b-button>
    </b-form>
    <b-card class="mt-3" header="Form Data Result">
      <pre class="m-0">{{ form }}</pre>
    </b-card>
  </div>
</template>

<script>
export default {
  name: "lowonganForm",
  data() {
    return {
      form: {
        jumlahlow: 1,
        checked: [],
        low: []
      },
      selow: [
        { text: "Pilih Satu", value: null, disabled: true },
        1,
        2,
        3,
        4,
        5,
        6
      ],
      show: true,
      target: false,
      buttonText: "Next"
    };
  },
  methods: {
    onSubmit(evt) {
      evt.preventDefault();
      alert(JSON.stringify(this.form));
      //   if (this.jumlahlow !== null || !this.jumlahlow < 1) {
      //     this.show = false;
      //   }
    },
    onReset(evt) {
      evt.preventDefault();
      // Reset our form values
      this.form.jumlahlow = null;
      this.form.checked = [];
      // Trick to reset/clear native browser form validation state
      this.show = false;
      this.$nextTick(() => {
        this.show = true;
      });
    }
  },
  computed: {}
};
</script>

  • 1
    This looks like an XY problem to me. I think you're going about it the wrong way from the start. – Decade Moon Mar 17 '20 at 09:23
  • Maybe, i need to send job openings email, min is 1, max is 6 job openings(parent), in each openings there are 1-15 job descriptions(child), and 1-15 requirements(child, brother). How do you suggest i do this in vue? Actually asking, not sarcasm Edit:the email sending part would be the backend's problem, i just need to send these datas. – Michael Chow Mar 17 '20 at 09:34

3 Answers3

2

You should try to model your data for how you want the view to be rendered. If you want to have a list of input boxes, then the data for those inputs should be defined in an array that is prepopulated with those items, or when you need to adjust the number of items you should add those data items to the array. You'll avoid reactivity problems this way too.

Here's an example of what I mean:

new Vue({
  el: '#app',
  
  data: {
    maxCount: 5,
    count: 3,
    items: [],
    data: '',
  },
  
  computed: {
    visibleItems() {
      return this.items.slice(0, this.count)
    }
  },
  
  created() {
    // Define the data upfront so it will be reactive
    for (let i = 0; i < this.maxCount; i++) {
      this.items.push({
        firstName: '',
        lastName: '',
      })
    }
  },
  
  methods: {
    submit() {
      // Transform the data into some JSON that is
      // compatible with your API
      const data = this.visibleItems.map(item => ({
        first_name: item.firstName,
        last_name: item.lastName,
        role: 'user',
      }))
      
      this.data = JSON.stringify(data, null, '  ')
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <div>
    Number of people:
    <select v-model="count">
      <option v-for="i of maxCount" :value="i">{{ i }}</option>
    </select>
  </div>
  
  <div v-for="item of visibleItems">
    <input placeholder="First name" v-model="item.firstName">
    <input placeholder="Last name" v-model="item.lastName">
  </div>
  
  <button @click="submit">Submit</button>
  
  <pre>{{ data }}</pre>
</div>
Decade Moon
  • 32,968
  • 8
  • 81
  • 101
1

Try this example.

<div id="app">
  <div>
    <select v-model="jumlahlow">
      <option v-for="i in selects" :key="i">{{ i }}</option>
    </select>
  </div>
  <div v-for="num, index in parseInt(jumlahlow)">
    <input v-model="lows[index].value" />
  </div>
</div>

And JS

new Vue({
  el: '#app',
  data: {
      lows: [
        {
        value: ''
      }
    ],
    jumlahlow: 1,
    selects: [
            1,
        2,
        3,
        4,
        5,
        6
    ]
  },
  watch: {
    jumlahlow: function (val) {
        this.lowsTmp = this.lows;
        this.lows = [];
        for (let i = 0; i < val; i++) {
        const currentVal = typeof this.lowsTmp[i] !== 'undefined' ? this.lowsTmp[i].value : '';
        this.addLow(currentVal);
      }
    }
  },
  methods: {
    addLow: function(val) {
        this.lows.push({ value: val });
    }
  }
})

Directly check here: https://jsfiddle.net/abinhho/m3c8r4tj/2/

Binh Ho
  • 3,690
  • 1
  • 31
  • 31
0

you are iterating v-for="n in parseInt(form.jumlahlow)" but that's an Object and v-for works on array not on objects.

Here you can use array of objects to iterate, for example:-

form: [{
    jumlahlow: 1,
    checked: [],
    low: []
  }]

and after that you will have to write v-for="n in form" then try accessing low by form.low

Anant Vikram Singh
  • 538
  • 1
  • 4
  • 14
  • nope, returned invalid array length error. It seems my explanation is a bit wrong, what i want to do is iterate the form group X times based on the select's value which could be either one, two or three and then access the iterated form group's input's v-model values to axios post them. – Michael Chow Mar 17 '20 at 08:59
  • post your code here or show some snap of it so i can see where the error is coming from – Anant Vikram Singh Mar 17 '20 at 09:00
  • Could you please re-production it in jsfiddle? – Binh Ho Mar 17 '20 at 09:06