Home > database >  Vue how to group items in v-for loop
Vue how to group items in v-for loop

Time:02-09

I have an array of objects, which contains menu's from a restaurant, where the user can choose a timeslot where the menu can be delivered.

here is an example of a menu object:

{
  date: '2022-02-10',
  slots: [
     {
       stock: 10,
       start: '06:00',
       end: '08:00',
     },
     {
       stock: 8,
       start: '10:00',
       end: '12:00',
     },
     {
       stock: 3,
       start: '12:00',
       end: '14:00',
     },
     {
       stock: 3,
       start: '14:00',
       end: '16:00',
     },
     {
       stock: 3,
       start: '16:00',
       end: '18:00',
     },
     {
       stock: 20,
       start: '18:00',
       end: '20:00',
     },
     {
       stock: 8,
       start: '20:00',
       end: '22:00',
     },
  ],
},

and here is how I render them:

<div v-for="(slot, index) in slots" :key="index">
   <input type="radio" :id="index" name="slot" />
   <label :for="index">
        {{ slot.start.slice(0, 2) }} - {{ slot.end.slice(0, 2) }}
   </label>
</div>

so far so good. Now I want to group the timeslots into "morning", "afternoon" and "evening" based on the time and display them like this:

Morning
06 - 08    10 - 12

Afternoon
12 - 14    14 - 16   16 - 18

Evening
18 - 20   20 - 22

How can I achieve that??

Thanks in advance...

CodePudding user response:

Group the menu slots by the end time then render them using two v-for :

Vue.config.devtools = false;
Vue.config.productionTip = false;

function pushToSlotTime(acc, slotTime, curr) {
  if (acc[slotTime]) {
    acc[slotTime].push(curr);
  } else {

    acc[slotTime] = [];
    acc[slotTime].push(curr);
  };
  return acc;
}
new Vue({
  el: '#app',

  data() {
    return {
      menu: {
        date: '2022-02-10',
        slots: [{
            stock: 10,
            start: '06:00',
            end: '08:00',
          },
          {
            stock: 8,
            start: '10:00',
            end: '12:00',
          },
          {
            stock: 3,
            start: '12:00',
            end: '14:00',
          },
          {
            stock: 3,
            start: '14:00',
            end: '16:00',
          },
          {
            stock: 3,
            start: '16:00',
            end: '18:00',
          },
          {
            stock: 20,
            start: '18:00',
            end: '20:00',
          },
          {
            stock: 8,
            start: '20:00',
            end: '22:00',
          },
        ],
      },
    }
  },
  computed: {
    groupedMenuSlots() {
      return this.menu.slots.reduce((acc, curr) => {
        let [end] = curr.end.split(':')
        if ( end <= 12) {
          return pushToSlotTime(acc, 'morning', curr)
        } else if ( end > 12 &&  end <= 18) {
          return pushToSlotTime(acc, 'afternoon', curr)
        } else {
          return pushToSlotTime(acc, 'evening', curr)
        }
      }, {})
    }

  }
})
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>


<div id="app" >
  <div v-for="(slots,key, index) in groupedMenuSlots" :key="index">
    <div>{{key}}</div>
    <span  v-for="slot in slots">
      <input type="radio" :id="index" name="slot" />
      <label :for="index">
         {{ slot.start.slice(0, 2) }} - {{ slot.end.slice(0, 2) }}
   </label>
    </span>
  </div>
</div>

  •  Tags:  
  • Related