Rooneyl
Rooneyl

Reputation: 7902

Vue multiple options per loop

Trying to display multiple options in Vue2 for loop of a select.

Given an object with the structure;

sorting = {
    name: [
        'asc',
        'desc'
    ],
    price: [
        'cheapest',
        'expensive'
    ]
}

How to format the loop to get the output of;

<select>
    <option value="name:asc">name asc</option>
    <option value="name:desc">name desc</option>
    <option value="price:cheapest">name cheapest</option>
    <option value="price:expensive">name expensive</option>
</select>

Can't work out the way to show the second option;

<select id="sortBy" class="form-control pr-3" v-model="sortBy">
    <option
        v-for="(options, sort) in sorting" :key="`${sort}`"
        v-bind:value="`${sort}:${options[0]}`"
    >
        {{ sort }} {{ options[0] }}
    </option>
</select>

Upvotes: 1

Views: 421

Answers (2)

Steven Spungin
Steven Spungin

Reputation: 29109

Use two option loops.

<select id="sortBy" class="form-control pr-3" v-model="sortBy">
    <option
        v-for="n in options.name" :key="`name:${n}`"
        :value="`name:${n}`"
    >
        name {{ n }}
    </option>
    <option
        v-for="p in options.price" :key="`price:${p}`"
        :value="`price:${p}`"
    >
        price {{ p }}
    </option>
</select>

Upvotes: 0

Terry
Terry

Reputation: 66133

That is because your sorting data contains nested arrays: you need to iterate through each keys (you've done done), and the also iterate through the array in each key to generate the options.

My suggestion is that instead of trying to do that in the template, which can be verbose and less readable... you can abstract that into a computed property that handles the option generation for you.

The trick here is simply using Object.entries() (which returns a key and value tuple) and then iterating through the value to return the key:arrayValue combination. Use Array.prototype.flatMap to flatten the returned array:

new Vue({
  el: '#app',
  data: {
    sorting: {
      name: [
        'asc',
        'desc'
      ],
      price: [
        'cheapest',
        'expensive'
      ]
    },
    sortBy: '',
  },
  computed: {
    options() {
      return Object.entries(this.sorting).flatMap(([key, optionsByKey]) => {
        return optionsByKey.map(v => `${key}:${v}`);
      });
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <select id="sortBy" class="form-control pr-3" v-model="sortBy">
    <option v-for="(option, i) in options" :key="i" :value="option">
      {{ option.replace(':', ' ') }}
    </option>
  </select>
  <br /><br />
  Selected value: {{ sortBy }}
</div>

Upvotes: 1

Related Questions