[Vuejs]-How to handle nested arrays with a v-for

0đź‘Ť

You need multiple divs with multiple v-for’s to handle multiple levels of an array.

Or you can use a reducer: https://www.robinwieruch.de/javascript-reducer/

Or a filter: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

to extract out the appropriate “series” key then you can just iterate over the single level array.

Using Methods in vueJs will be the ideal way to format your data so your templating is more elegant.

0đź‘Ť

Here’s a working component using your data as carData:

<template>
  <div>
    <select v-model="make">
      <option v-for="m in makes" :key="m.id" :value="m">{{ m.make }}</option>
    </select>
    <select v-model="model">
      <option v-for="m in models" :key="m.id" :value="m">{{ m.name }}</option>
    </select>
    <select v-model="year">
      <option v-for="y in years" :key="y" :value="y">{{ y }}</option>
    </select>
  </div>
</template>

<script>
const CAR_DATA = {
  '1': {
    id: 1,
    make: 'Subaru',
    models: [
      {
        id: 1,
        name: 'Forrester',
        years: [2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020],
        series: [
          {
            id: 1,
            name: 'SH',
            years: [2009, 2010, 2011, 2012],
          },
          {
            id: 2,
            name: 'SJ',
            years: [2012, 2013, 2014, 2015, 2016, 2017, 2018],
          },
          {
            id: 3,
            name: 'SK',
            years: [2018, 2019, 2020],
          },
        ],
      },
      {
        id: 2,
        name: 'Impreza',
        years: [2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020],
        series: [
          {
            id: 1,
            name: 'GJ',
            years: [2011, 2012, 2013, 2014, 2015, 2016],
          },
          {
            id: 2,
            name: 'GT',
            years: [2017, 2018, 2019, 2020],
          },
        ],
      },
    ],
  },
  '2': {
    id: 2,
    make: 'Toyota',
    models: [
      {
        id: 1,
        name: 'Camry',
        years: [2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020],
        series: [
          {
            id: 1,
            name: 'XV40',
            years: [2009, 2010, 2011, 2012],
          },
          {
            id: 2,
            name: 'XV70',
            years: [2017, 2018, 2019, 2020],
          },
        ],
      },
      {
        id: 2,
        name: '4Runner',
        years: [2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020],
        series: [
          {
            id: 1,
            name: 'N210',
            years: [2009],
          },
          {
            id: 2,
            name: 'GT',
            years: [2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020],
          },
        ],
      },
    ],
  },
};

export default {
  data() {
    return {
      make: null,
      model: null,
      year: null,
      carData: CAR_DATA,
    };
  },
  computed: {
    makes() {
      return Object.values(this.carData);
    },
    models() {
      return this.make ? this.make.models : [];
    },
    years() {
      return this.model ? this.model.years : [];
    },
  },
};
</script>

The nice thing about this implementation is that you don’t actually have to traverse the object. The trick is entirely in choosing the right value object for each option.

Leave a comment