antd的穿梭框a-transfer实现:树形列表,父节点多选,子节点单选,父子节点联动

项目需求:

     1,穿梭框中为树形列表,a-transfer + a-table(table 数据为treeData);

     2,父节点为多选,子节点是单选

          穿梭框左边的列表需要满足父子节点联动:勾选子节点时默认选中父节点,选中父节点时默认勾选子节点(初次默认选中第1个子节点,否则选中上次勾选的子节点),取消勾选父节点同时取消勾选的子节点;

          穿梭到右边的列表不需要父子节点联动,穿梭过去时需要保留子节点选中状态,同时父节点清空选中状态。

代码如下:

<a-transfer
     titles="标题"
    :data-source="configData"
    :target-keys="targetKeys"
    :show-search="true"
    :filter-option="(inputValue, item) => item.title.indexOf(inputValue) !== -1"
    :show-select-all="false"
    pagination
    @change="onChange"
    >
      <template
         slot="children"
         slot-scope="{
              props: { direction, filteredItems, selectedKeys, disabled: listDisabled },               
              on: { itemSelectAll, itemSelect },
               }"
              >
        <a-table
           :row-selection="getRowSelection({ disabled: listDisabled, 
                                             selectedKeys, 
                                             itemSelectAll, 
                                             itemSelect, 
                                             findGoalRow })"
           :columns="direction === 'left' ? leftColumns : rightColumns"
           :data-source="filteredItems"
           size="small"
           >
               <template slot="isNeed" slot-scope="text, record">
                 <a-radio-group name="radioGroup" v-model="record.isNeed" :default-value="record.isNeed">
                    <a-radio :value="true"> 是 </a-radio>
                    <a-radio :value="false"> 否  </a-radio>  
                  </a-radio-group>
                  <span> {{text}}</span>
                </template>

---------------子节点插槽--------------------
                <template slot="expandedRowRender" slot-scope="row, index" >
                    <a-table 
                       disabled
                       v-if="row.childrenNode.length > 0"
                       :columns="innerColumns" 
                       :dataSource="row.childrenNode"
                       :rowSelection="{
                           selectedRowKeys: row.checkedKey || [], 
                           hideDefaultSelections: true,
                           onChange: (selectedRowKeys, selectedRows) => 
                           onSelectChangeInner(selectedRowKeys, selectedRows, row, index, itemSelect),
                           type: 'radio'}" 
                      :pagination="false" 
                      :showHeader="false" />
               </template>

            </a-table>
          </template>
      </a-transfer>

---------------获取,处理data数据--------
  this.configData = res.result.map(obj => {
             if(obj.children){
                  obj.children.forEach((t,i)=>{
                    obj.children[i].key = obj.children[i].id //列表数据必须设置唯一key
                
                })
              }
              return {
                  key: obj.id,
                  id:  obj.id,
                  title: obj.name,
                  disabled: false,
                  isNeed: false,
                  description: '',
                  childrenNode: obj.children || [], //取消树形数据默认效果
                  checkedKey: obj.checkedKey || [], //选中的子节点key
                  firstCheckedKey: obj.children ? obj.children[0].key : '', //第一个子节点key
                }
              });   
             this.configDataKeys = this.configData.map(t=>t.key) 

---------------methods-------------------
      import difference from 'lodash/difference';

      //1,穿梭框点击事件
      onChange(nextTargetKeys,direction) {
        console.log('onChange--',this.targetKeys,nextTargetKeys)
        const leftDataList = difference(this.configDataKeys,nextTargetKeys)
        if(direction === 'left'){
          //穿梭到左边:增加字段标识,清空子节点选中状态
          leftDataList.forEach(t=>{
            let row = this.findGoalRow(t)
            if(row.length > 0){
              row[0].checkedKey[0] = ''
              row[0].direction = direction
            }
          })
        }else{
          //穿梭到右边:增加字段标识
          nextTargetKeys.forEach(t=>{
            let row = this.findGoalRow(t)
            if(row.length > 0){
              row[0].direction = direction
            }
          })
        }
        this.targetKeys = nextTargetKeys;
       },

    //2,父节点全选,选中,取消选中事件
    getRowSelection({ disabled, selectedKeys, itemSelectAll, itemSelect, findGoalRow }) {
        console.log('主表勾选--',selectedKeys)
        return {
          onSelectAll(selected, selectedRows) {
            const treeSelectedKeys = selectedRows
              .filter(item => !item.disabled)
              .map(({ key }) => key);
            const diffKeys = selected
              ? difference(treeSelectedKeys, selectedKeys)
              : difference(selectedKeys, treeSelectedKeys);
            //全选时:默认选中子节点
            //取消全选时:取消选中的子节点
            diffKeys.forEach(t=>{
              let row = findGoalRow(t)
              if(row.length > 0){
                if(row[0].direction !== 'right'){
                  row[0].checkedKey[0] = selected ? (row[0].beforeCheckedKey || row[0].firstCheckedKey) : ''
                }
              }
            })
         
            itemSelectAll(diffKeys, selected);
          },

          onSelect({ key }, selected) {
            console.log('onSelect--',key,selected,selectedKeys)
            let selectedRow = findGoalRow(key)
            if(!selected){
              let index = selectedKeys.indexOf(key)
              console.log('index',index,'selectedKeys',selectedKeys)
              if(index !== -1){
                selectedKeys.splice(index,1)
              }
              //取消勾选父节点的同时取消子节点的勾选
              if(selectedRow[0].direction !== 'right'){
                selectedRow[0].checkedKey = []
              }
            }else{
              if(!selectedKeys.includes(key)){
                selectedKeys.push(key)
              }
              //勾选父节点,如果子节点没有勾选则默认选中第一条,如果子节点上次有勾选则恢复上次勾选
              selectedRow[0].checkedKey[0] = selectedRow[0].beforeCheckedKey || selectedRow[0].firstCheckedKey
            }
            itemSelect(key, selected);
          },

          selectedRowKeys: selectedKeys,
        };
      },

     //3,子节点选中事件(子节点为单选,只能选中,其父节点取消选中时则子节点也取消选中)
     onSelectChangeInner(selectedRowKey, selectionRow, row, index, itemSelect){
        console.log('单选',selectedRowKey, selectionRow,row.key,index)
        this.$set(row, 'checkedKey', selectedRowKey);
        this.$set(row, 'beforeCheckedKey', selectedRowKey[0]);
        //左边列表:父子节点勾选联动
        //右边列表:父子节点勾选不联动
        if(row.direction !== 'right'){
          itemSelect(row.key, true)
        }
      },  

    //4,根据key找对应的row
    findGoalRow(key){
        return this.configData.filter(t=>t.key === key)
      },

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值