Home > Net >  v-bind an array in a menu value but get individual item in the array
v-bind an array in a menu value but get individual item in the array

Time:01-18

Hope you all can help here.

I have a drop-down menu that I'm using v-bind to assign an array to the selected value. See below-

<select v-model="selected" name="SKU[]"   @onChange>
  <option v-for="infos in data" v-bind:value="{ level: infos.stockLevel, SKU: infos.SKU }"  @change="onChange($event)" >{{infos.SKU}} </option>
</select>

There are multiple menus and I'm storing the selected options in SKU[] and then passing them to a form via a post.

The problem is my controller is now reading SKU[] as this:

array:2 [▼
  0 => "[object Object]"
  1 => "[object Object]"
]

I want to store infos.SKU in SKU[], not object object.

Any idea how I can do this?

CodePudding user response:

You can't store javascript objects in html. You can use there only strings, so you should call JSON.stringify() method with your object and then pass into value. Than you will be able to use it as an object after JSON.parse(). But the best case is to use another vue component for options or pass only id of object in value

CodePudding user response:

Instead of passing an event in @change event, you can directly pass the selected v-model attribute and then push the data object into SKU data variable.

Live Demo :

new Vue({
  el: '#app',
  data: {
    data: [{
      stockLevel: 'Level 1',
      SKU: 'SKU 1'
    }, {
      stockLevel: 'Level 2',
      SKU: 'SKU 2'
    }, {
      stockLevel: 'Level 3',
      SKU: 'SKU 3'
    }, {
      stockLevel: 'Level 4',
      SKU: 'SKU 4'
    }],
    selected: '',
    SKU: []
  },
  methods: {
    onChange(selectedValue) {
      if (!JSON.stringify(this.SKU).includes(JSON.stringify(selectedValue))) {
        this.SKU.push(selectedValue);
      }
      console.log(this.SKU);
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <select v-model="selected" @change="onChange(selected)">
    <option 
            v-for="(infos, index) in data" 
            :key="index" 
            v-bind:value="{ level: infos.stockLevel, SKU: infos.SKU }"
            >
      {{infos.SKU}} 
    </option>
  </select>
</div>

CodePudding user response:

First of all, I am not sure how are you managing multiple selections because without using the multiple prop or any other way, at a time only a single value would be displayed as selected which seems vague from a "multiple-selection UI" perspective.

Secondly, there is no @onchange syntax, it should be either onchange or @change.

Third, the @change event should fire on the select element, not the option element.

At last, your v-model is what you are using to bind the selected element, then why not use that to track the selected element?

Here is the working demo-

<html>
  <div id="app">
    {{ SKU }}<br>
    <select v-model="selected" @change="onChange">
      <option
        v-for="infos in data"
        :value="{ level: infos.stockLevel, SKU: infos.SKU }"
        >{{ infos.SKU }}
      </option>
    </select>
  </div>
  <!-- Don't forget to include Vue from CDN! -->
  <script src="https://unpkg.com/vue@2"></script>
  <script>
    new Vue({
      el: "#app", //Tells Vue to render in HTML element with id "app"
      data() {
        return {
          SKU: [],
          selected: null,
          data: [{
              stockLevel: "Stock level 1",
              SKU: "SKU 1",
            },
            {
              stockLevel: "Stock level 2",
              SKU: "SKU 2",
            },
          ],
        };
      },
      methods: {
        onChange() {
          // Do not push if already exists. I assumed "SKU" was a unique property.
          if (this.SKU.find(item => item.SKU == this.selected.SKU)) return;

          this.SKU.push(this.selected)
        },
      },
    });
  </script>
</html>

  • Related