[Vuejs]-How to select single cell when there are multiple editable cells on Ant Design Vue 3?

0👍

TL;DR:

use composite key, like editableData[row + '|' + column] to target row and column for editing.

The example (that I assume you intended to link) has a couple shortcomings.

If you’ll pardon the "pedantics", I’ll explain what the example does first. I’ve kept the important bits here:

// in template:  @click="edit(record.key)"

// in setup:
const editableData = reactive({});

function edit(key){
  editableData[key] = JSON.parse(
    JSON.stringify(dataSource.value.filter((item) => key === item.key)[0])
  );
}

editableData is a reactive object that will store two parameters the key and the copy of the entire object. for example assigning editableData[2] = {...} will allow the save method to replace the 3rd item (key) to the altered copy. One issue with that is that all the fields in the same row are tied together. So if you edit two, but only save one, they will both be updated. The second issue is that there is no way to target which specific value in the object you are making editable. Additionally, relying on the copy of an entire object, could cause some issues if the underlying data is mutable through some other path.

There are couple different ways to solve for this issue, but I’ll just share, what I believe to be, the simplest, which is to use a composite key.

instead of editableData[key] = {a copy of row object} you can use editableData[rowKey + "|"+ colKey] = 12 (12 being example of the value when user hits edit)

it would look something like this:

template:

<template
  v-for="col in editableCells"
  #[col]="{ column, text, record }"
  :key="col"
>
  <div class="editable-cell">
    <div
      v-if="editableData[record.key + '|' + column.key]"
      class="editable-cell-input-wrapper"
    >
      <a-input
        v-model:value="editableData[record.key + '|' + column.key]"
        @pressEnter="save(record.key, column.key)"
      />
      <check-outlined
        class="editable-cell-icon-check"
        @click="save(record.key, column.key)"
      />
    </div>
    <div v-else class="editable-cell-text-wrapper">
      {{ text || ' ' }}
      <edit-outlined
        class="editable-cell-icon"
        @click="edit(record.key, column.key)"
      />
    </div>
  </div>
</template>

script:

const edit = (row, column) => {
  editableData[row + '|' + column] = dataSource.value.filter(
    (item) => row === item.key
  )[0][column];
};

const save = (row, column) => {
  dataSource.value[row][column] = editableData[row + '|' + column];
  delete editableData[row + '|' + column];
};

I’m using the pipe character as a separation character to concatenate the two strings, you can omit that and just use row + column which should resolve to a string and not cause any issues. This can be handy though if you have a potential for conflicting keys (such as both being indexes)

Leave a comment