VisActor / VisActor/VTable

[Bug] 自定义排序,或自定义筛选的状态下,进行编辑表格内容后,筛选的结果被重置了。

Open
#4,429 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
TypeScript
Stars
3.7k
Forks
486
Avg merge
1d 19h
Merged PRs (30d)
16

Description

Version

1.19.3

Link to Minimal Reproduction

页面代码在重现步骤中

Steps to Reproduce
<style>
.sortClass {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}
.header-title {
  width: 100%;
  display: flex;
  justify-content: space-between;
}

.vtable-list1.sort-caret {
  width: 0;
  height: 0;
  border: solid 5px transparent;
  position: absolute;
  left: 7px;
}
.vtable-list1 .sort-caret.ascending {
  border-bottom-color: var(--el-text-color-placeholder);
  top: -5px;
}
.vtable-list1 .caret-wrapper {
  display: flex;
  flex-direction: column;
  align-items: center;

  width: 24px;
  justify-items: flex-start;
  cursor: pointer;
  overflow: initial;
  position: relative;
}
</style>
<template>
  <div :style="{ height: '100%', width: '100%' }" class="vtable-list1">
    <ListTable :options="option" :records="records" ref="tableRef">
      <!-- Order Number Column -->
      <ListColumn
        :field="item.field"
        :title="item.title"
        v-for="(item, index) in columns"
        :key="item.field"
        :width="item.width"
        :aggregation="item.aggregation"
        editor="input-editor"
      >
        <template
          v-if="item.field"
          #headerCustomLayout="{ table, row, col, rect, record, width, height }"
        >
          <Group
            :height="height"
            :width="width"
            display="flex"
            flexDirection="row"
            flexWrap="nowrap"
            :vue="{}"
          >
            <div class="bloggerName" style="pointer-events: all">
              <div v-if="item.field != 'index'" class="header-title">
                <div>{{ item.title }}</div>
                <span class="caret-wrapper">
                  <el-icon v-if="item.sortType == 'normal'" @click="sortClick('desc', item.field)"
                    ><DCaret
                  /></el-icon>
                  <el-icon v-if="item.sortType == 'desc'" @click="sortClick('aesc', item.field)"
                    ><CaretTop color="#409eff"
                  /></el-icon>
                  <el-icon v-if="item.sortType == 'aesc'" @click="sortClick('normal', item.field)"
                    ><CaretBottom color="#409eff"
                  /></el-icon>
                </span>
              </div>

              <input
                v-model="form[item.field]"
                placeholder="搜索内容"
                @change="(e) => handInputChange(e, item.field)"
                style="width: 100%; border: 1px solid; margin: 2px"
              />
            </div>
          </Group>
        </template>
      </ListColumn>
    </ListTable>
  </div>
</template>

<script setup>
import { ref, reactive, onMounted, getCurrentInstance } from 'vue'
import { ListTable, ListColumn, register } from '@visactor/vue-vtable'
import { Group, Text, Image, Radio, CheckBox, Tag } from '@visactor/vue-vtable'
import { DateInputEditor, InputEditor, ListEditor, TextAreaEditor } from '@visactor/vtable-editors'
import * as VTable from '@visactor/vtable'

const tableRef = ref()

const percentCalc = VTable.CustomLayout.percentCalc
const columns = [
  {
    type: 'text',
    title: '产品名称',
    field: 'productName',
    width: '150px',
    sortType: 'normal',
    aggregation: {
      aggregationType: VTable.TYPES.AggregationType.NONE,
      formatFun(value) {
        return '总计:'
      },
    },
  },
  { type: 'text', title: '单片名称', field: 'pieceName', width: '150px', sortType: 'normal' },
  { type: 'numeric', title: '宽', field: 'width', width: '120px', sortType: 'normal' },
  { type: 'numeric', title: '高', field: 'height', width: '120px', sortType: 'normal' },
  {
    type: 'numeric',
    title: '数量',
    field: 'num',
    width: '120px',
    sortType: 'normal',
    aggregation: {
      aggregationType: VTable.TYPES.AggregationType.SUM,
      formatFun(value) {
        return value
      },
    },
  }]
const form = reactive({})

onMounted(() => {
  window.top.postMessage(
    {
      at: 'dd',
      type: 'childMounted',
      data: {
        data: [],
      },
    },
    '*',
  )
  tableRef.value.vTableInstance.on('change_cell_value', changeEditCell)
  tableRef.value.vTableInstance.on('dblclick_cell', dblclickCellClick)
  tableRef.value.vTableInstance.on('dropdown_menu_click', dropclickCellClick)


function dropclickCellClick(args) {
  let tableInstance = tableRef.value.vTableInstance
  if (args.menuKey === '向上插入空行') {
    const recordIndex = tableInstance.getRecordShowIndexByCell(args.col, args.row)
    if (recordIndex) {
      tableInstance.addRecord({}, recordIndex - 1)
    } else {
      tableInstance.addRecord({}, 0)
    }
  } else if (args.menuKey === '向下插入空行') {
    const recordIndex = tableInstance.getRecordShowIndexByCell(args.col, args.row)
    tableInstance.addRecord({}, recordIndex + 1)
  } else if (args.menuKey === '删除该行') {
    const recordIndex = tableInstance.getRecordShowIndexByCell(args.col, args.row)
    tableInstance.deleteRecords([recordIndex])
  }
}

function changeEditCell() {
  console.log('changeEditCell')
}
function dblclickCellClick(data) {
  if (data.row) {
    // Object.keys(form).forEach((key) => {
    //     form[key] = ''
    // })
  }
}

function sortClick(action, id) {
  columns.forEach((value, index) => {
    if (value.field == id) {
      value.sortType = action
    } else {
      value.sortType = 'normal'
    }
  })
  if (!action) return
  tableRef.value.vTableInstance.updateSortState({
    field: id,
    order: action,
  })
  tableRef.value.vTableInstance.renderWithRecreateCells()
}

function handInputChange(e, type) {
  tableRef.value.vTableInstance.updateFilterRules([
    {
      filterFunc: (record) => {
        // console.log(form, 'form')
        // Object.keys(form).forEach((key) => {
        //   console.log(key, 'key')
        //   if (key != type) {
        //     form[key] = ''
        //   }
        // })
        // if (!record) return
        return String(record[type]).includes(form[type])
      },
    },
  ])
}

let records = ref([{ productName: '234234' }, { productName: '234234' }, { productName: '234234' }])

const inputEditor = new InputEditor()
const textAreaEditor = new TextAreaEditor()
const dateInputEditor = new DateInputEditor()

register.editor('input-editor', inputEditor)
const option = {
  defaultRowHeight: 80,
  //  defaultColWidth:160,
  defaultHeaderRowHeight: 80,
  containerFit: {
    width: true,
    height: true,
  },
  customConfig: {
    createReactContainer: true,
  },
  keyboardOptions: {
    moveEditCellOnArrowKeys: true,
    copySelected: true,
    pasteValueToCell: true,
  },
  dragOrder: {
    dragHeaderMode: 'column',
  },
  widthMode: 'standard',
  bottomFrozenRowCount: 1,
  emptyTip: {
    text: '无数据',
  },
  menu: {
    contextMenuItems: ['向上插入空行', '向下插入空行', '删除该行'],
  },
  rowSeriesNumber: {
    title: '序号',
    width: 'auto',
    headerStyle: {
      color: 'black',
      bgColor: '',
    },
    style: {
      color: 'black',
    },
  },
}
</script>
<style>
.bloggerName {
  /* width: 330px;; */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
</style>
Current Behavior

搜索筛选后,编辑单元格后,全量数据会立即重置
例如:筛选出一条数据,编辑状态下,编辑后,数据会被立即重置成3条数据。

Expected Behavior

搜索筛选后,编辑单元格后,数据条数不应变化
例如:筛选出一条数据,编辑状态下,编辑后,数据保持1条

Environment
- OS:macOS Monterey
- Browser:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0
- Framework:Vue@3.5.17
Any additional comments?

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the Vue reproduction in the issue and reproduce the sequence of applying updateFilterRules, editing a cell through input-editor, and observing the change_cell_value event. Trace how filtering and editing interact after the edit. Done means the filtered result remains unchanged after editing, such as one visible row remaining when one row matched before the edit.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
frontend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.