Search code examples
javascripthtmlarraysvue.jsv-for

Showing even indexes in one column and odd indexes in another column using v-for


I want to show the even indexes of my array myArray:

   myArray: [{'label': 'hasan', 'value': 'hosein'},
            {'label': '1', 'value': '2'},
            {'label': 'gholi', 'value': 'gholam'},
            {'label': '3', 'value': '4'},
            {'label': 'an', 'value': 'goh'},
            {'label': '5', 'value': '6'},
            {'label': 'pashm', 'value': 'khar'},
            {'label': '7', 'value': '8'}]

in the right and odd indexes on the left column using v-for.

This is my HTML code:

      <div class="row" v-for="objData in myArray" :key="objData.label">
        // right column
        <div class="line col-2"></div>
        <div class="line col-3 "></div>
        // left column
        <div class="line col-2"></div>
        <div class="line col-3 "></div>
      </div>

I tried to separate the odd and even indexes into two new arrays and added a <div> above <div class="row> with a new v-for to loop through both arrays in my separate <div>s but it scrambled my array elements. So how can I show even indexes of myArray on the right and odd indexes on the left column?


Solution

  • Spoiler: I like the last one better

    You could either use this trick with i and v-if:

    new Vue({
      el: '#app',
      data() {
        return {
           myArray: [{label:"hasan",value:"hosein"},{label:"1",value:"2"},{label:"gholi",value:"gholam"},{label:"3",value:"4"},{label:"an",value:"goh"},{label:"5",value:"6"},{label:"pashm",value:"khar"},{label:"7",value:"8"}]
        };
      }
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.21/vue.min.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap-grid.min.css" />
    
    <div id="app" class="container">
      <div class="row">
        <div class="col-sm">
          <template v-for="(objData, i) in myArray" :key="objData.label">
            <div v-if="i%2">{{objData.label}}</div>
          </template>
        </div>
        <div class="col-sm">
          <template v-for="(objData, i) in myArray" :key="objData.label">
            <div v-if="!(i%2)">{{objData.label}}</div>
          </template>
        </div>
      </div>
    </div>

    Or separate your array in two in a computed prop, using reduce:

    new Vue({
      el: '#app',
      data() {
        return {
           myArray: [{label:"hasan",value:"hosein"},{label:"1",value:"2"},{label:"gholi",value:"gholam"},{label:"3",value:"4"},{label:"an",value:"goh"},{label:"5",value:"6"},{label:"pashm",value:"khar"},{label:"7",value:"8"}]
        };
      },
      computed: {
        splitArray() {
          const [ evens, odds ] = this.myArray.reduce((res, item, i) => {
            res[i % 2].push(item);
            return res;
          }, [[], []]);
          return { evens, odds };
        }
      }
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.21/vue.min.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap-grid.min.css" />
    
    <div id="app" class="container">
      <div class="row">
        <div class="col-sm">
          <div v-for="objData in splitArray.odds" :key="objData.label">
            {{objData.label}}
          </div>
        </div>
        <div class="col-sm">
          <div v-for="objData in splitArray.evens" :key="objData.label">
            {{objData.label}}
          </div>
        </div>
      </div>
    </div>

    ... And if you want to go further, and not have to repeat yourself in the template:

    new Vue({
      el: '#app',
      data() {
        return {
           myArray: [{label:"hasan",value:"hosein"},{label:"1",value:"2"},{label:"gholi",value:"gholam"},{label:"3",value:"4"},{label:"an",value:"goh"},{label:"5",value:"6"},{label:"pashm",value:"khar"},{label:"7",value:"8"}]
        };
      },
      computed: {
        splitArray() {
          return this.myArray.reduce((res, item, i) => {
            res[1 - i % 2].push(item);
            return res;
          }, [[], []]);
        }
      }
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.21/vue.min.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap-grid.min.css" />
    
    <div id="app" class="container">
      <div class="row">
        <div v-for="(col, i) in splitArray" :key="`col-${i}`" class="col-sm">
          <div v-for="objData in splitArray[i]" :key="objData.label">
            {{objData.label}}
          </div>
        </div>
      </div>
    </div>