Skip to content
Advertisement

How to create function that creates new grid-item onClick? Vuex using vue-grid-layout

I am using vue-grid-layout to create a draggable tile system, which will keep track of the order of steps to be executed by a system in our research lab. In short, I can create as many grid-item elements as I want by hard coding them, but I need to be able to create a function that will create/remove additional grid-items. I am stumped as to how to approach this since I suck at JavaScript, to create a grid-item in HTML I can do the following:

//these are just the ‘settings’ for the grid items//

    <h2 style="color: #f6a821;">Steps</h2>
      <hr class="hr" />
      <grid-layout
        :layout.sync="stepsGrid"
        :col-num="8"
        :row-height="75"
        :is-draggable="true"
        :is-resizable="false"
        :is-mirrored="false"
        :vertical-compact="true"
        :margin="[50, 50]"
        :use-css-transforms="true">

//here we actually create the grid-item, starting at [0]
       <grid-item
          :x=stepsGrid[0].x
          :y=stepsGrid[0].y
          :w=stepsGrid[0].w
          :h=stepsGrid[0].h
          :i=stepsGrid[0].i
          :isDraggable=stepsGrid[0].isDraggable>

          <div class="Panel__name">1</div>
          <div class="editButton">
            <router-link to="/Parameters-template" class="editButton">Edit</router-link></router-link>
          </div><br>
          <div class="Panel__status">Status:</div>

        </grid-item>

I am essentially needing to know how I can click to add as many of these as I want, but I am unsure of how to program this. If I currently have this one grid-item, I need to press a button that will create another grid-item at :

<grid-item
      :x=stepsGrid[1].x
      :y=stepsGrid[1].y
      :w=stepsGrid[1].w
      :h=stepsGrid[1].h
      :i=stepsGrid[1].i
      :isDraggable=stepsGrid[1].isDraggable>

 ... content
</grid-item>

-and would increment from 0 up through 1,2,3 etc. I have the states for the grid-layouts as follows:

import Vue from 'vue';
import Vuex from 'vuex';

import createPersistedState from 'vuex-persistedstate'

Vue.use(Vuex);

export const store = new Vuex.Store({
    //strict: process.env.NODE_ENV !== 'production',
    state: {
        stepsGrid : [
            {"x":0,"y":0,"w":2,"h":1,"i":"0"},
            {"x":2,"y":0,"w":2,"h":1,"i":"1"},
            {"x":4,"y":0,"w":2,"h":1,"i":"2"},
            {"x":6,"y":0,"w":2,"h":1,"i":"3"},
            {"x":0,"y":2,"w":2,"h":1,"i":"4"},
            {"x":2,"y":2,"w":2,"h":1,"i":"5"}
        ],
.......
        mutations: {
        state.stepsGrid = [
            {"x":0,"y":0,"w":2,"h":1,"i":"0"},
            {"x":2,"y":0,"w":2,"h":1,"i":"1"},
            {"x":4,"y":0,"w":2,"h":1,"i":"2"},
            {"x":6,"y":0,"w":2,"h":1,"i":"3"},
            {"x":0,"y":2,"w":2,"h":1,"i":"4"},
            {"x":2,"y":2,"w":2,"h":1,"i":"5"}
                       ],

Answer

You need to use v-for to loop over your data and create each of the items.

In the example below I haven’t used grid-layout or grid-item but the principle is exactly the same.

const store = new Vuex.Store({
    state: {
        stepsGrid: [
            {x: 0, y: 0, w: 2, h: 1, i: 0}
        ]
    },
    
    mutations: {
        addStep (state, step) {
            state.stepsGrid.push(step);
        }
    },
    
    actions: {
        addStep ({state, commit}) {
            const step = {x: 2, y: 0, w: 2, h: 1, i: state.stepsGrid.length};

            commit('addStep', step);
        }
    }
});

new Vue({
    el: '#app',
    store,

    computed: {
        stepsGrid () {
            return this.$store.state.stepsGrid;
        }
    },

    methods: {
        onClick () {
            this.$store.dispatch('addStep');
        }
    }
});
<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>
<script src="https://unpkg.com/vuex@3.1.1/dist/vuex.js"></script>
<div id="app">
  <ul>
    <li v-for="step in stepsGrid">{{ step }}</li>
  </ul>
  <button @click="onClick">Add step</button>
</div>

So in your case it would be:

<grid-item
    v-for="step in stepsGrid"
    :x="step.x"
    :y="step.y"
    :w="step.w"
    :h="step.h"
    :i="step.i"
    :isDraggable="step.isDraggable">

You could potentially simplify this down to:

<grid-item
    v-for="step in stepsGrid"
    v-bind="step">

Relevant documentation for rendering lists:

https://v2.vuejs.org/v2/guide/list.html
https://v2.vuejs.org/v2/api/#v-for

Advertisement