2

I have a list of cars as below:

<script>

const sampleCars = [
  {
    id: 1,
    name: 'Cressida',
    model: 'XXC',
    manufacturer: 'Toyota',
    price: '$10,000',
    inEditMode: false 
  },
  {
    id: 2,
    name: 'Corolla',
    model: 'ZD-2',
    manufacturer: 'Toyota',
    price: '$12,000',
    inEditMode: false 
  },
  {
    id: 3,
    name: 'Condor',
    model: '27-9',
    manufacturer: 'Mazda',
    price: '$8,000',
    inEditMode: false 
  }
]

export default {
  data() {
    return {
      cars: sampleCars
    }
  }
}


</script>

<style>
.grid {
  display: grid;
  grid-template-columns: repeat(5, auto);
  gap: 10px;
}

</style>

I want to display the items in a css grid with 5 columns.

If I use vue code like below:

<template>
  <div >
    <div class="grid">
      <div>Name</div>
      <div>Model</div>
      <div>Manufacturer</div>
      <div>Price</div>
      <div>buttons</div>      
    </div>
    <div v-for="car in cars" :key="car.id" class="grid">
      <div>{{car.name}}</div>  // "child div"
      <div>{{car.model}}</div>
      <div>{{car.manufacturer}}</div>
      <div>{{car.price}}</div>
      <div>buttons</div>
    </div>
  </div>
</template>

The problem with this code is that each item is displayed in its own grid. (And therefore not aligned as in image below). Using v-for all car properties become a child of the root div. So essentially I want all "child divs" to be a root of one CSS grid div. How can I achieve that?

enter image description here

With VueJS 2

1
  • well, you assigning the grid class for each row, so each row is its own grid. there are plenty of resources of how you can create a table with css grid, you should take a look at some. Commented Oct 23, 2020 at 9:55

2 Answers 2

2

Make the table header in one grid and table rows in another grid :

Vue.config.devtools = false;
Vue.config.productionTip = false;
const sampleCars = [{
    id: 1,
    name: 'Cressida',
    model: 'XXC',
    manufacturer: 'Toyota',
    price: '$10,000',
    inEditMode: false
  },
  {
    id: 2,
    name: 'Corolla',
    model: 'ZD-2',
    manufacturer: 'Toyota',
    price: '$12,000',
    inEditMode: false
  },
  {
    id: 3,
    name: 'Condor',
    model: '27-9',
    manufacturer: 'Mazda',
    price: '$8,000',
    inEditMode: false
  }
]

new Vue({
  el: '#app',

  data() {
    return {
      cars: sampleCars
    }
  }
})
.grid {
  display: grid;
  grid-template-columns: repeat(5, minmax(92px,1fr));
  gap: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>


<div id="app" class="container">

  <div>
    <div class="grid">
      <div>Name</div>
      <div>Model</div>
      <div>Manufacturer</div>
      <div>Price</div>
      <div>buttons</div>
    </div>
    <div v-for="car in cars" :key="car.id">
      <div class="grid">
        <div>{{car.name}}</div>
        <div>{{car.model}}</div>
        <div>{{car.manufacturer}}</div>
        <div>{{car.price}}</div>
        <div>buttons</div>
      </div>
    </div>
  </div>
</div>

Sign up to request clarification or add additional context in comments.

1 Comment

Yeah, that's what I am looking for, but that does not work for me. In the compile error message it says that "Elements in iteration expect to have 'v-bind:key'". But also, I cannot use :key with template element "'<template>' cannot be keyed."
2

The best solution I found was to use Vue-Fragment from https://github.com/Thunberg087/vue-fragment

The child elements in the v-for loop will end up being at the root level:

<template>
  <div >
    <div class="grid">
      <div>Name</div>
      <div>Model</div>
      <div>Manufacturer</div>
      <div>Price</div>
      <div>buttons</div>  

      <fragment v-for="car in cars" :key="car.id"  >
        <div>{{car.name}}</div>
        <div>{{car.model}}</div>
        <div>{{car.manufacturer}}</div>
        <div>{{car.price}}</div>
        <div>buttons</div>
      </fragment>     
    </div>   

  </div>
</template>

See also this SO question: Is there something like React.Fragment in Vue?

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.