primefaces / primevue

Next Generation Vue UI Component Library
https://primevue.org
MIT License
10.24k stars 1.21k forks source link

DataTable: Setting sortField or v-model:filters Attributes Causes Data to Revert/Save Incorrectly When Editing Multiple Rows #3587

Open nathanhennig opened 1 year ago

nathanhennig commented 1 year ago

Describe the bug

On a DataTable with editMode="row" and the sortField attribute set, if you open multiple rows for editing, change values on multiple rows then save a row, the data in the other rows will revert to the original values.

If you then change the values again on the open rows and click cancel, those values do not revert to the original values.

Setting the v-model:filters attribute has the same effect.

As a side note, I had some trouble discovering the source of this behavior as I was using stateStorage="local" and the filters and sortField did not consistently clear from localStorage after removing those attributes, then rebuilding and refreshing the page (FireFox 109.0 (64-bit)).

Reproducer

https://codesandbox.io/s/optimistic-https-0mbwcu?file=/src/App.vue

PrimeVue version

3.12.4

Vue version

3.x

Language

ES6

Build / Runtime

Vue CLI App

Browser(s)

FireFox 109.0 , Chrome 109.0

Steps to reproduce the behavior

sortField Reproduction

  1. Go to the sortField reproducer at https://codesandbox.io/s/optimistic-https-0mbwcu?file=/src/App.vue
  2. Click the edit pencils on the first two rows and change the price values to any numbers different from the originals.
  3. Click save on the first row and note that the second row's value has reverted.
  4. Change the value on the second row again.
  5. Click cancel and note that the value has not reverted and remains changed.

v-model:filters Reproduction

  1. Go to the filters reproducer at https://codesandbox.io/s/serene-lucy-ouqvj4?file=/src/App.vue.
  2. Perform steps 2-5 from the sortField Reproduction above and note the exact same behavior.

Expected behavior

I expect when the sortField and/or v-model:filters attributes are set and I am editing multiple rows, that row data will only be saved when I click the save button for that row and only and always revert when I click the cancel button.

nathanhennig commented 1 year ago

I now believe I understand at least part of this issue, although I still don't understand all the mechanics at work.

This issue actually triggers if the table is sorted at all, not just by having the sortField attribute set initially on the DataTable.

Saving a row triggers the processedData function in DataTable.vue. processedData is called after saving a row reactively because the table data has changed.

        processedData() {
            let data = this.value || [];

            if (!this.lazy) {
                if (data && data.length) {
                    if (this.hasFilters) {
                        data = this.filter(data);
                    }

                    if (this.sorted) {
                        if (this.sortMode === 'single') data = this.sortSingle(data);
                        else if (this.sortMode === 'multiple') data = this.sortMultiple(data);
                    }
                }
            }

            return data;
        }

If the table has filters or is sorted, filter/sortSingle/sortMultiple is called. All three of those functions call:

        clearEditingMetaData() {
            if (this.editMode) {
                this.d_editingMeta = {};
            }
        }

It seems to be that clearing the editing meta data when no actual sorting or filtering has occurred is the source of the issue since it is not called if sorted and hasFilters are false, in which case all row editing works perfectly.

I may be missing something since I don't understand why clearing the editing meta data is necessary before sorting and filtering. If the table can't safely be sorted/filtered while rows are in edit mode, then I think it would be better to wait to re-sort/re-filter until no rows are being edited, rather than break row editing.

nathanhennig commented 1 year ago

Hmm. I just tested disabling the editing meta data clear while sorting and the row data changes based on the sort? It changes between displaying the rowEditingData and the original data. Editing it while it displays the original data results in it being persisted (i.e. clicking cancel on that row will not revert to the original data).

For my purposes I think I can just remove the editing meta data clear in my fork and disable the sorting and filtering UI while editingRows.length > 0, but I really have no idea what the proper solution for the library itself is.

ethic40 commented 5 months ago

Use :


 let { newData } = event;
  let index = items.value.findIndex(m => m.id === newData.id)
  items.value[index] = newData;