I understand from the caveats portion of the Vue docs that updating a value in an array in the following manner will not work:
  this.arr[idx] = newVal
and that one should use splice(). I am using a 2D array to store grid data, and I am having a difficult time updating the value when a cell in the grid is clicked.
Here is my template:
  <tr
      v-for="(row, rowKey, index) in grid"
        :key="rowKey">
        <th
          class="row-col-label"
        >{{rowKey+1}}</th>
        <td
            v-for="(col, colKey, index) in row"
            :key="colKey"
            @click="selectCell(rowKey, colKey)"
            :class="{'selected' : cellSelected(rowKey, colKey)}"
        >
        {{col}}
        </td>
      </tr>
And here is the relevant code for the Vue component:
 created () {
  this.initColHead()
  this.createSpreadSheet()
 },
 data () {
  return {
   selected: '',
   grid: [],
   colHead: [' '],
   isSelected: false
 }
},
methods: {
 initColHead () {
   this.colHead.push(...'ABC'.split(''))
 },
 createSpreadSheet () {
   for (let i = 0; i <= 2; i++) {
     this.grid[i] = []
      for (let j = 0; j <= 2; j++) {
       this.grid[i][j] = false
      }
   }
 },
selectCell (row, col) {
  this.isSelected = true
  console.log(`row ${row} col ${col}`)
  this.grid[row].splice(col, 1, true)
  for (let i = 0; i <= 2; i++) {
    for (let j = 0; j <= 2; j++) {
      console.log(this.grid[i][j])
    }
  }
},
cellSelected (row, col) {
  return (this.grid[row][col] === true)
}
}
So I am attempting to add a true value to the cell that is click at the given row col locations provided in the my selectCell method. However, the data in my grid is not updated to reflect the newly added value. How exactly do I update values in a multidimensional array in Vue?
One method that works:
selectCell (row, col) {
  //make a copy of the row
  const newRow = this.grid[row].slice(0)
  // update the value
  newRow[col] = true
  // update it in the grid
  this.$set(this.grid, row, newRow)
},
Here is an example.
console.clear()
new Vue({
  el: "#app",
  created() {
    this.initColHead()
    this.createSpreadSheet()
  },
  data() {
    return {
      selected: '',
      grid: [],
      colHead: [' '],
      isSelected: false
    }
  },
  methods: {
    initColHead() {
      this.colHead.push(...'ABC'.split(''))
    },
    createSpreadSheet() {
      for (let i = 0; i <= 2; i++) {
        this.grid[i] = []
        for (let j = 0; j <= 2; j++) {
          this.grid[i][j] = false
        }
      }
    },
    selectCell(row, col) {
      const newRow = this.grid[row].slice(0)
      newRow[col] = true
      this.$set(this.grid, row, newRow)
    },
    cellSelected(row, col) {
      return (this.grid[row][col] === true)
    }
  }
})
.selected {
  background-color: green;
}
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<div id="app">
  <table>
    <tr v-for="(row, rowKey, index) in grid" :key="rowKey">
      <th class="row-col-label">{{rowKey+1}}</th>
      <td v-for="(col, colKey, index) in row" :key="colKey" @click="selectCell(rowKey, colKey)" :class="{'selected' : cellSelected(rowKey, colKey)}">
        {{col}}
      </td>
    </tr>
  </table>
</div>
If I think of something better I'll update later.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With