VTable icon indicating copy to clipboard operation
VTable copied to clipboard

[Feature] 当点击合并Checkbox的单元格时,能够整合勾选状态。

Open huhaosanxiong opened this issue 10 months ago • 2 comments

What problem does this feature solve?

目的:

  • 在点击合并Checkbox单元格的空白处时,能够有和点击Checkbox一样的效果

当前做法:

  • 在CLICK_CELL事件中,获取当前单元格的勾选状态getCellCheckboxState,然后通过setCellCheckboxState设置相反的状态

在以下代码中出现问题:

  • 点击红色框里的区域时,能勾选Checkbox。再点击蓝色区域时,无法取消勾选Checkbox(图1)。分析原因:点击红色区域后实际只修改了bloggerId为3的那行的勾选状态(图2)。
  • 当主动调用setCellCheckboxState的方式把bloggerId为4和5的两行设置为和bloggerId为3的相同的CheckboxState时,发现不生效,对应的状态依然是true, undefined, undefined

期望: 1、当调用setCellCheckboxState时,如果命中的是合并的单元格,能否把Checkbox的状态都统一设置? 2、或者作者有什么其他的更好的解决方法😁

图1: Image

图2: Image

代码如下:

const VGroup = VTable.VGroup;
const VText = VTable.VText;
const VImage = VTable.VImage;
const VTag = VTable.VTag;
const VRadio = VTable.VRadio;
const VCheckBox = VTable.VCheckBox;

const option = {
  container: document.getElementById('container'),
  columns: [
    {
      field: 'serial',
      title: '选择',
      width: 200,
      minWidth: 80,
      disableColumnResize: true,
      cellType: 'checkbox',
      headerType: 'checkbox',
      mergeCell: true,
    },
    {
      field: 'bloggerId',
      title: 'bloggerId',
      width: 150,
    },
    {
      field: 'bloggerName',
      title: 'bloggerName',
      width: 330
    },
    {
      field: 'fansCount',
      title: 'fansCount',
      fieldFormat(rec) {
        return rec.fansCount + 'w';
      },
      style: {
        fontFamily: 'Arial',
        fontSize: 12,
        fontWeight: 'bold'
      }
    },
    {
      field: 'worksCount',
      title: 'worksCount',
      style: {
        fontFamily: 'Arial',
        fontSize: 12,
        fontWeight: 'bold'
      }
    },
    {
      field: 'viewCount',
      title: 'viewCount',
      fieldFormat(rec) {
        return rec.fansCount + 'w';
      },
      style: {
        fontFamily: 'Arial',
        fontSize: 12,
        fontWeight: 'bold'
      }
    },
    {
      field: 'viewCount',
      title: 'viewCount',
      fieldFormat(rec) {
        return rec.fansCount + 'w';
      },
      style: {
        fontFamily: 'Arial',
        fontSize: 12,
        fontWeight: 'bold'
      }
    },
    {
      field: '',
      title: 'operation',
      width: 100,
      icon: ['favorite', 'message']
    }
  ],
  records: [
    {
      bloggerId: 1,
      bloggerName: 'Virtual Anchor Xiaohua',
      bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/flower.jpg',
      introduction:
        'Hi everyone, I am Xiaohua, the virtual host. I am a little fairy who likes games, animation and food. I hope to share happy moments with you through live broadcast.',
      fansCount: 400,
      worksCount: 10,
      viewCount: 5,
      city: 'Dream City',
      tags: ['game', 'anime', 'food'],
      serial: 1
    },
    {
      bloggerId: 2,
      bloggerName: 'Virtual anchor little wolf',
      bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/wolf.jpg',
      introduction:
        'Hello everyone, I am the virtual anchor Little Wolf. I like music, travel and photography, and I hope to explore the beauty of the world with you through live broadcast.',
      fansCount: 800,
      worksCount: 20,
      viewCount: 15,
      city: 'City of Music',
      tags: ['music', 'travel', 'photography'],
      serial: 1
    },
    {
      bloggerId: 3,
      bloggerName: 'Virtual anchor bunny',
      bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/rabbit.jpg',
      introduction:
        'Hello everyone, I am the virtual anchor Xiaotu. I like painting, handicrafts and beauty makeup. I hope to share creativity and fashion with you through live broadcast.',
      fansCount: 600,
      worksCount: 15,
      viewCount: 10,
      city: 'City of Art',
      tags: ['painting', 'handmade', 'beauty makeup'],
      serial: 2
    },
    {
      bloggerId: 4,
      bloggerName: 'Virtual anchor kitten',
      bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/cat.jpg',
      introduction:
        'Hello everyone, I am the virtual host Kitty. I am a lazy cat who likes dancing, fitness and cooking. I hope to live a healthy and happy life with everyone through the live broadcast.',
      fansCount: 1000,
      worksCount: 30,
      viewCount: 20,
      city: 'Health City',
      tags: ['dance', 'fitness', 'cooking'],
      serial: 2
    },
    {
      bloggerId: 5,
      bloggerName: 'Virtual anchor Bear',
      bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bear.jpg',
      introduction:
        'Hello everyone, I am the virtual host Xiaoxiong. A little wise man who likes movies, reading and philosophy, I hope to explore the meaning of life with you through live broadcast.',
      fansCount: 1200,
      worksCount: 25,
      viewCount: 18,
      city: 'City of Wisdom',
      tags: ['Movie', 'Literature'],
      serial: 2
    },
    {
      bloggerId: 6,
      bloggerName: 'Virtual anchor bird',
      bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bird.jpeg',
      introduction:
        'Hello everyone, I am the virtual anchor Xiaoniao. I like singing, acting and variety shows. I hope to be happy with everyone through the live broadcast.',
      fansCount: 900,
      worksCount: 12,
      viewCount: 8,
      city: 'Happy City',
      tags: ['music', 'performance', 'variety'],
      serial: 3
    },
  ],
  defaultRowHeight: 40,
};

const instance = new VTable.ListTable(document.getElementById(CONTAINER_ID), option);
window.tableInstance = instance;

const {
  CHECKBOX_STATE_CHANGE,
  CLICK_CELL
} = VTable.ListTable.EVENT_TYPE;

// 多选框状态改变
instance.on(CHECKBOX_STATE_CHANGE, (...args) => {
  console.log(CHECKBOX_STATE_CHANGE, args)
  const checkboxState = instance.getCheckboxState('serial')
  console.log('[VTable] 获取多选框状态 =>', checkboxState);
});

//点击cell
instance.on(CLICK_CELL, (...args) =>  {
  console.log(CLICK_CELL, args)
  const { originData, target, field, col, row } = args[0]
  if (target && target instanceof VTable.CustomLayout.CheckBox) {
    // 点击复选框, 不进行任何操作
    return
  }
  // 点击的是选择框列的空白处
  if (originData && col === 0 && field === 'serial') {
    // 选择框列
    const state = instance.getCellCheckboxState(col, row)
    // 状态取反
    instance.setCellCheckboxState(col, row, !state)
  }
});

What does the proposed API look like?

如上。

huhaosanxiong avatar Feb 12 '25 09:02 huhaosanxiong

可以在CLICK_CELL的回调中做一下range判断,调用table.getCellRange(col,row)获取一下单元格的range,如果发现是多个单元格合并,那就分别调用一下setCellCheckboxState,这样应该可以

Rui-Sun avatar Feb 13 '25 11:02 Rui-Sun

可以在CLICK_CELL的回调中做一下range判断,调用table.getCellRange(col,row)获取一下单元格的range,如果发现是多个单元格合并,那就分别调用一下setCellCheckboxState,这样应该可以

经过验证:合并单元格分别调用setCellCheckboxState,只会第一个设置的单元格生效,后面设置的不会触发CHECKBOX_STATE_CHANGE 事件。

//点击cell
instance.on(CLICK_CELL, (...args) =>  {
  console.log(CLICK_CELL, args)
  const { originData, target, field, col, row } = args[0]
  if (target && target instanceof VTable.CustomLayout.CheckBox) {
    // 点击复选框, 不进行任何操作
    return
  }
  // 点击的是选择框列的空白处
  if (originData && col === 0 && field === 'serial') {
    if (row === 1) {
      // 模拟点击body的第一行
      // 是合并单元格,分别对row为1和2的单元格设置setCellCheckboxState
      instance.setCellCheckboxState(col, 1, true)
      instance.setCellCheckboxState(col, 2, true)
    }else {
      // 选择框列
      const state = instance.getCellCheckboxState(col, row)
      // 状态取反
      instance.setCellCheckboxState(col, row, !state)
    }
  }
});

对合并单元格的row分别调用setCellCheckboxState的结果:只有row为1的行变更了勾选状态。

Image

为了验证是否真的是同个合并单元格内的row首次调用才生效,调整一下顺序,结果:确实是只生效首次调用setCellCheckboxState的行。

Image

huhaosanxiong avatar Feb 14 '25 06:02 huhaosanxiong