Search code examples
javascriptcssvue.jsgrid-layoutbootstrap-vue

How to dynamically render elements in a grid


I am trying to create a layout in which each row would contains 3 cards. for that i tried using Grid layout of bootstrap, so as to make it responsive.

But the problem is I would be having data of cards in the JSON format. and the JSON Object array length may vary i.e (number of cards to render on the screen may vary).

I some how need to render it dynamically, using ViewJS, bootstrap-vue & JSON.

I figured it out that the Number of objects in JSON would refer to number of cards in the screen and number of cards/ 3 = number of rows

I am not getting on how to render the cards in the grid dynamically.

I am using Vue-js and bootstrap-vue to get the task done, but I am stuck with it.

CardRenderer.vue:

<template lang="html">

  <div>
    <hr>   
    <b-container class="bv-example-row">
  <b-row>
    <b-col>
      <b-card
        title= "renderObject.title"
        img-src="https://picsum.photos/600/300/?image=25"
        img-alt="Image"
        img-top
        tag="article"
        style="max-width: 20rem;"
        class="mb-2"
      >
      <b-card-text>
        Some quick example text to build on the card title and make up the bulk of the card's content.
      </b-card-text>

      <b-button href="#" variant="primary">Go somewhere</b-button>
      </b-card>
    </b-col>
    <b-col>
      <b-card
        title= "renderObject.title"
        img-src="https://picsum.photos/600/300/?image=25"
        img-alt="Image"
        img-top
        tag="article"
        style="max-width: 20rem;"
        class="mb-2"
      >
      <b-card-text>
        Some quick example text to build on the card title and make up the bulk of the card's content.
      </b-card-text>

      <b-button href="#" variant="primary">Go somewhere</b-button>
      </b-card>
    </b-col>
    <b-col>
      <b-card
        title= "renderObject.title"
        img-src="https://picsum.photos/600/300/?image=25"
        img-alt="Image"
        img-top
        tag="article"
        style="max-width: 20rem;"
        class="mb-2"
      >
      <b-card-text>
        Some quick example text to build on the card title and make up the bulk of the card's content.
      </b-card-text>

      <b-button href="#" variant="primary">Go somewhere</b-button>
      </b-card>
    </b-col>
  </b-row>
</b-container>

  </div>

</template>

<script lang="js">
  export default  {
    name: 'CardRenderer',
    props: {
      passer: Object
    },
    mounted() {
      // eslint-disable-next-line
      console.log(this.renderObject);
    },
    data() {
      return {

      }
    },
    methods: {

    },
    computed: {

    }
  }
</script>

<style scoped>

</style>

This is a sort of a static structure of the page. All the card that is being renderer needs to be rendered according to the JSON passed and all the data is stored in JSON itself.

How do i dynamically render cards in grid layout?


Solution

  • You could try using a computed property that sorts the array for you.

    <script lang="js">
        export default {
            name: 'CardRenderer',
            props: {
                passer: Object
            },
            mounted() {
                // eslint-disable-next-line
                console.log(this.renderObject);
            },
            data() {
                return {
    
                }
            },
            methods: {
    
            },
            computed: {
                rows() {
                    var rows = []
                    var itemsPerRow = 3
                    // assuming passer is an array of items..
                    var arr = this.passer
                    for (var i = 0; i<arr.length; i+=itemsPerRow){
                        var row = []
                        for (var z = 0; z<itemsPerRow; z++) {
                            row.push(arr[i + z])
                        }
                        rows.push(row)
                    }
                    return rows
                }
            }
        }
    </script>
    

    Then you can loop through the rows in your template. Something like this

    <template lang="html">
        <div>
            <hr>
            <b-container class="bv-example-row">
                <b-row v-for="row in rows">
                    <b-col v-for="item in row">
                        <!-- you card -->
                        <b-card title="renderObject.title" img-src="https://picsum.photos/600/300/?image=25" img-alt="Image" img-top tag="article" style="max-width: 20rem;" class="mb-2">
                            <b-card-text>
                                <h1>item data:</h1>
                                <pre>{{item}}</pre>
                            </b-card-text>
                            <b-button href="#" variant="primary">Go somewhere</b-button>
                        </b-card>
                    </b-col>
                    </b-col>
                </b-row>
            </b-container>
        </div>
    </template>
    

    I don't know what your data looks like but it's recommended when using v-for to also include a key. If your data doesn't contain a suitable attribute for that you can use the array index as key. See more here https://v2.vuejs.org/v2/guide/list.html#Maintaining-State