0

I am re-vamping a program for my Engineering departments research team, my app has been built using Electron, Vuex, HTML/Sass/Javascript. The program's purpose is to allow the user to create "steps" which are items/tiles that you can go into & set system parameters & processes to run X amount of times. Setting up the values and settings within each step can take a while, so if the user creates 5 steps, and realizes they want to delete step number 2 entirely, there needs to be a 'remove' or a small 'x' within each step/item. Currently, I can only remove the last populated step/item using the 'pop' function to remove the last item in the array 'stepsGrid'.

Using vue-grid-layout to populate grid-items/tiles which will each be a 'step' that our system will run. I am able to dynamically add new 'steps', however I have only been able to successfully remove steps by using pop() to remove the last item from the array in which grid-items are. I want to place a

<button id="remove" @click="removeStep()">Remove</button>

within each step, so that I can delete any item on the grid instead of just the last item.

I have seen a few examples, but not being the best at javascript- I haven't had any luck. I tried referencing the functions used here: https://chrishamm.io/grid-demo/ and https://github.com/chrishamm/vue-dynamic-grid for removing grid items, however this library is a little more complicated than the regular Vue-Grid-Layout.

Here is my code, the key is the step.i component which is the ID of each item populated, each tile will have an 'x' in the corner and the function needs to be able to recognize the ID of that tile, and delete the corresponding item from the stepsGrid array:

<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">

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

<div class="Panel__name">Step: {{step.i}} //displays item # on each tile
<div class="Panel__stepcount"> Loop Count: <input type="number" value="1">
 </div>
</div>
<div class="editButton">
<div class="Panel__status">Status:</div>
<button @click="removeStep()">Remove</button>


</grid-item>
</grid-layout>

//Grid arrays are in store.js, as shown below(this is for an electron app):

import Vue from 'vue';
import Vuex from 'vuex';
import createPersistedState from 'vuex-persistedstate'

Vue.use(Vuex);

export 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":0, "y": 1, "w": 2,"h":1,"i":String(state.stepsGrid.length) };
    commit('addStep', step);
 },

I know I need to incorporate the use of a key here, but I am unsure how to do it. I found this, but he goes about it an unusual way:

"I deleted the element in array by the button and could not understand the problem, as the last element was always deleted, although the key was unique. I added an extra unique uuid and it all worked."

<dish-item v-else class="dishItem" 
v-for="(item, key) in dishes" :key="key + $uuid.v1()" :value="item"
@removeDish="$delete(dishes, key)" 
@editDish="$refs.modal.showEdit({item, key})"
/>

Lastly, I went digging through the files for Vue-Dynamic-Grid and found that they are removing items with the following method:

methods: {
    removeElement(item) {
    if (item == this.selectedItem) {
    this.selectElement(null);
}

this.gridItems.splice(item.i, 1);
this.items.splice(item.i, 1);
breakpoints.forEach(function(size) {
    this.layouts[size].splice(item.i, 1);
    this.layouts[size].forEach(function(layout, i) {
       if (layout.i > item.i) {
         layout.i--;
        }
    });
}, this);
this.$emit("itemRemoved", item);
    }

If anyone could be of help, I would appreciate it! I have been learning JS on the go with this project, so if anyone has some tips please let me know! Thanks

I have tried attempting to write a function based on the way Vue-Dynamic-Layout's method for removing items, but I was not successful. As of right now, I don't have a small 'x' in each tile, I have a button for adding/removing a step in the bottom left of my app, to remove items I am simply popping the last item out of the stepsGrid array, so I can only remove the last populated item.

Lee Taylor
  • 7,761
  • 16
  • 33
  • 49

1 Answers1

0

First let the event handler know which step is being clicked

<button @click="removeStep(step)">Remove</button>

Then find that step in the array and remove it

methods: {
    removeStep(step) {
        const index = this.stepsGrid.indexOf(step);
        if (index >= 0) this.stepsGrid.splice(index, 1);
    }
}
Stephen Thomas
  • 13,843
  • 2
  • 32
  • 53
  • Thanks a bunch. This is working, however I'm running into a couple things here When I go to the page which has this steps grid, the first step is labeled with:
    Step: {{step.i}}
    where step.i starts at zero, so the first item is "Step: 0", now lets say I create 3 more steps, now I have steps 0, 1, 2, 3 If I delete step 2 I now have 0, 1, 3. If I add a new step, I will now have two Step 3's, and I get the error: *vue.esm.js?a026:628 [Vue warn]: Duplicate keys detected: '3'. This may cause an update error.*
    – julianstogs Aug 08 '19 at 22:40
  • The error message is correct. Keys should be unique. Since the `.i` property isn't unique, it can't be used as a key. Either use a different property (one that is unique) as a key, or refine the semantics of `.i` so that it is unique. – Stephen Thomas Aug 08 '19 at 23:42
  • Okay, I will look into doing that. So in the case that I have refined the `.i` property to be unique, would I need to change the code you provided me above? – julianstogs Aug 09 '19 at 02:15
  • Update: I seem to have found a workaround for the issue previously mentioned, I am using the index as the key and instead of each tile displaying the `Step: {{step.i}}` I have changed it to `Step: {{index}}` so that when I have steps `0, 1, 2, 3` and I delete step 1, steps 2 & 3 automatically change themselves to steps 1 & 2. Is there any reason why I may not want to approach the problem in this manner? Again, thank you for your help! – julianstogs Aug 09 '19 at 21:59
  • **Update: I thought all was working properly, I am not getting any errors but I am now seeing some issues in the programs behavior. Lets say I create 3 steps, I will now have steps `0, 1. 2, 3` , if I remove step 2, step 3 is now renamed to step 2. I now add another step, which is properly named step 3, however if I re-position/drag step 3, both 2 AND 3 drag at the same time. I know this is due to the indexing, I am looking into how I should refine `.i` so that it is unique but I can't seem to find a good method on how to do so. – julianstogs Aug 09 '19 at 22:04
  • I am trying to use UUID as key but I am having some issues. Not sure how to pass the UUID into the array, could help me out a bit? – julianstogs Aug 14 '19 at 17:53
  • link to new post: https://stackoverflow.com/questions/57499564/how-to-make-v-for-key-unique – julianstogs Aug 14 '19 at 17:53