简体   繁体   中英

How to display store items in v-for loop with Vuetify grid?

I am attempting to display card items in a v-for loop with Vuetify grid system. The loop is set up to iterate through dynamically inputted Firestore items returned to the template from a Vuex store file ("item in this.$store.getters.getItems"), which are then rendered as Vuetify cards. I was successful in setting up the loop to render the items in small cards inside a container. However, I want these cards to render in a grid. In other words, I want to create a breaking point so that after 3 cards, for example, the 4th, 5th, and 6th card drop down to a new row. How can I achieve this? I understand how to do this in a more simpler setup without a Vuex getter method in a v-for loop. But how does this work when Vuex methods start entering the picture? My code is below:

Home.vue

<template>
 <div id="home">
   <v-container>
     <v-text-field v-model="myTodo" placeholder="add input"></v-text-field>
     <v-btn @click="addToDo">Add</v-btn>
   </v-container>

  <v-container>
    <v-flex md7>
      <v-card class="elevation-0 transparent card-container grey">
        <v-card-title primary-title class="layout justify-center">
          <div class="headline text-xs-center">CARD CONTAINER</div>
        </v-card-title>
        <v-flex d-flex>
          <v-card class="card-container" v-for="item in this.$store.getters.getItems" :key="item.id">
            {{ item.title }}<v-btn @click="deleteItem(item.id)">Delete</v-btn>
          </v-card>
        </v-flex>
      </v-card>
    </v-flex>
  </v-container>
 </div>
</template>

<script>
import { db } from '@/main'

export default {
  name: 'home',
  beforeCreate: function () {
    this.$store.dispatch('setItems')
  },
  data: function () {
    return {
      myTodo: '',
      errors: ''
    }
  },
  methods: {
    addToDo: function () {
      this.errors = ''
      if (this.myTodo !== '') {
        db.collection('items').add({
          title: this.myTodo,
          created_at: Date.now()
        }).then((response) => {
          if (response) {
            this.myTodo = ''
          }
        }).catch((error) => {
          this.errors = error
        })
      } else {
        this.errors = 'Please enter some text'
      }
    },
    deleteItem: function (id) {
      if (id) {
        db.collection("items").doc(id).delete().then(function() {
          console.log('Document successfully deleted')
        }).catch(function(error) {
          this.error = error
        })
      } else {
        this.error = 'Invalid ID'
      }
    }
  }
}
</script>

<style>
  .card-container {
    margin: 10px;
    padding: 10px;
  }
</style>

store.js

import Vue from 'vue'
import Vuex from 'vuex'
import { db } from '@/main'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    items: null
  },
  getters: {
    getItems: state => {
      return state.items
    }
  },
  mutations: {
    setItems: state => {
      let items = []
      db.collection('items').orderBy('created_at').onSnapshot((snapshot) => {
        items = []
        snapshot.forEach((doc) => {
          items.push({ id: doc.id, title: doc.data().title })
        })
        state.items = items
      })
    }
  },
  actions: {
    setItems: context => {
      context.commit('setItems')
    }
  }
})

Actually you're just creating a list of cards and they are going to be displayed inside a v-flex without any further directive.

To have a grid layout you should use the v-layout plus the v-flex .

<v-flex d-flex>
   <v-layout wrap>
       <v-flex md4 v-for="item in this.$store.getters.getItems" :key="item.id">
           <v-card class="card-container">
            {{ item.title }}<v-btn @click="deleteItem(item.id)">Delete</v-btn>
          </v-card>
       </v-flex>
   </v-layout>
</v-flex>

In this code I wrap the cards with a v-layout with the wrap attribute, that don't need writing a new v-layout for the row.

The for loop is moved to the v-flex and I give the size 4 to the cell.

In the grid layout you have 12 box, if you need 3 you have to give a size of 4 (md4) each box.

If you need a much flexible layout you should put the v-layout inside the loop and print a new every time you want a new row.

Note

I'm new to vuetify, so not sure if there is a better way to achieve this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM