2.7K Star 16K Fork 3.6K

GVPLayui / layui

 / 详情

请问下treeTable能否对现有的数据集进行搜索并显示搜索结果在树形表中

已完成
创建于  
2023-06-09 09:13

版本号

2.8.6

问题描述

请问下treeTable能否对现有的树形表数据进行搜索并显示搜索结果在树形表中(非异步搜索服务端数据,仅对已加载的树形表中的数据进行搜索显示。应用场景:几百上千个菜单一次加载形成树形表进行搜索显示)
看了文档,可以通过 treeTable.getNodesByFilter 方法来获得想要的返回数据集,但这里获得了返回的搜索结果数据集后,不知道怎么显示到树形表中。

业务代码

var data = treeTable.getNodesByFilter('menus', function(item){
    return item.menu_name.indexOf(keywords) > -1;
});

截图补充

输入图片说明

友好承诺

我承诺将本着相互尊重、理解和友善的态度进行交流,共同维护 Layui 良好的社区氛围。

评论 (5)

Niaho 创建了任务

本地搜索的话有两种思路你试试看:
1、先把行记录全部隐藏,然后遍历数据找到符合的条件的行记录然后将他们显示回来,如果是树表,还要注意把他们的父行和祖辈给显示回来。这样做基本上就是一些隐藏和显示。
2、2.8.6 新增了一个方法,table.renderData, treeTable 也同样有这个方法,它的作用就是将表格的 cache 信息重新渲染,我觉得可以利用这个方法来实现你目前的需求,实际就是将 cache 过滤一下,然后重新 renderData 即可,但是也要注意如何恢复,目前没有对数据是否 hide 进行解析如果有的话就更方便只要处理 hide 信息即可。我本地写的了一个数移动的,你可以试试看有没有可以参考的

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>测试 table.renderData </title>
<!--  <link href="src/css/layui.css" rel="stylesheet">-->
  <link href="//unpkg.com/layui@2.8.6/dist/css/layui.css" rel="stylesheet">
  <style>
    html body {
      padding: 10px;
    }

    .layui-table-click {
      background-color: #ffb800;
    }
  </style>
</head>
<body>

<table id="table1"></table>
<hr>
<table id="table2"></table>

<script type="text/html" id="barDemo">
  <a class="layui-icon layui-icon-up" lay-event="move" data-direction="up"></a>
  <a class="layui-icon layui-icon-down" lay-event="move" data-direction="down"></a>
</script>

<!--<script src="src/layui.js"></script>-->
<script src="//unpkg.com/layui@2.8.6/dist/layui.js"></script>
<script>
  layui.use(['table'], function (table) {
    var $ = layui.jquery;
    table.render({
      elem: "#table1",
      toolbar: '<div><b>表格1,data模式</b></div>',
      data: [
        {
          "id": "10001",
          "username": "杜甫123",
          "email": "test1@email.com",
          "sex": "<strong style=\"color: red\">男</strong>",
          "city": "浙江杭州",
          "sign": "舍南舍北皆春水,但见群鸥日日来。花径不曾缘客扫,蓬门今始为君开。盘飧市远无兼味,樽酒家贫只旧醅。肯与邻翁相对饮,隔篱呼取尽余杯。",
          "experience": 7,
          "ip": "192.168.0.8",
          "checkin": 0,
          "joinTime": "2016-10-14",
          "LAY_DISABLED": true
        },
        {
          "id": "10002",
          "username": "李白",
          "email": "test2@email.com",
          "sex": "男",
          "city": "浙江杭州",
          "sign": "君不见,黄河之水天上来,奔流到海不复回。 君不见,高堂明镜悲白发,朝如青丝暮成雪。 人生得意须尽欢,莫使金樽空对月。 天生我材必有用,千金散尽还复来。 烹羊宰牛且为乐,会须一饮三百杯。 岑夫子,丹丘生,将进酒,杯莫停。 与君歌一曲,请君为我倾耳听。(倾耳听 一作:侧耳听) 钟鼓馔玉不足贵,但愿长醉不复醒。(不足贵 一作:何足贵;不复醒 一作:不愿醒/不用醒) 古来圣贤皆寂寞,惟有饮者留其名。(古来 一作:自古;惟 通:唯) 陈王昔时宴平乐,斗酒十千恣欢谑。 主人何为言少钱,径须沽取对君酌。 五花马,千金裘,呼儿将出换美酒,与尔同销万古愁。",
          "experience": 9,
          "ip": "192.168.0.8",
          "checkin": "106",
          "joinTime": "2016-10-14",
          "LAY_CHECKED": true
        },
        {
          "id": "10003",
          "username": "苏轼",
          "email": "test3@email.com",
          "sex": "男",
          "city": "浙江杭州",
          "sign": "大江东去,浪淘尽,千古风流人物。故垒西边,人道是,三国周郎赤壁。乱石穿空,惊涛拍岸,卷起千堆雪。江山如画,一时多少豪杰。遥想公瑾当年,小乔初嫁了,雄姿英发。羽扇纶巾,谈笑间,樯橹灰飞烟灭。故国神游,多情应笑我,早生华发。人生如梦,一尊还酹江月。",
          "experience": 8,
          "ip": "192.168.0.8",
          "checkin": null,
          "joinTime": "2016-10-14"
        },
        {
          "id": "10004",
          "username": "李清照",
          "email": "test4@email.com",
          "sex": "女",
          "city": "浙江杭州",
          "sign": "人生恰似一场修行",
          "experience": 6,
          "ip": "192.168.0.8",
          "checkin": "106",
          "joinTime": "2016-10-14"
        },
        {
          "id": "10005",
          "username": "冰心",
          "email": "test5@email.com",
          "sex": "女",
          "city": "浙江杭州",
          "sign": "人生恰似一场修行",
          "experience": 64,
          "ip": "192.168.0.8",
          "checkin": "106",
          "joinTime": "2016-10-14"
        },
        {
          "id": "10006",
          "username": "张三",
          "email": "test6@email.com",
          "sex": "男",
          "city": "浙江杭州",
          "sign": "人生恰似一场修行",
          "experience": 65,
          "ip": "192.168.0.8",
          "checkin": "106",
          "joinTime": "2016-10-14"
        },
        {
          "id": "10007",
          "username": "张三7",
          "email": "test7@email.com",
          "sex": "男",
          "city": "浙江杭州",
          "sign": "人生恰似一场修行",
          "experience": 49,
          "ip": "192.168.0.8",
          "checkin": "106",
          "joinTime": "2016-10-14"
        },
        {
          "id": "10008",
          "username": "张三8",
          "email": "test8@email.com",
          "sex": "男",
          "city": "浙江杭州",
          "sign": "人生恰似一场修行",
          "experience": 5,
          "ip": "192.168.0.8",
          "checkin": "106",
          "joinTime": "2016-10-14"
        },
        {
          "id": "10009",
          "username": "张三9",
          "email": "test9@email.com",
          "sex": "男",
          "city": "浙江杭州",
          "sign": "人生恰似一场修行",
          "experience": 5,
          "ip": "192.168.0.8",
          "checkin": "106",
          "joinTime": "2016-10-14"
        },
        {
          "id": "10010",
          "username": "张三10",
          "email": "test10@email.com",
          "sex": "男",
          "city": "浙江杭州",
          "sign": "人生恰似一场修行",
          "experience": 5,
          "ip": "192.168.0.8",
          "checkin": "106",
          "joinTime": "2016-10-14"
        },
        {
          "id": "10011",
          "username": "张三11",
          "email": "test11@email.com",
          "sex": "男",
          "city": "浙江杭州",
          "sign": "人生恰似一场修行",
          "experience": 5,
          "ip": "192.168.0.8",
          "checkin": "106",
          "joinTime": "2016-10-14"
        }
      ],
      cols: [[
        {field: 'id', hide: true}
        , {type: 'numbers'}
        , {field: 'username', title: '用户名'}
        , {field: 'email', title: '邮箱'}
        , {field: 'joinTime', title: '日期'}
        , {field: 'experience', title: '积分', totalRow: true}
        , {field: 'checkin', title: '迁入', totalRow: true}
        , {title: '操作', align: 'center', toolbar: '#barDemo'}
      ]],
      page: true,
      totalRow: true,
      done: function (res, curr, count) {
        var tableView = this.elem.next();
        tableView.find('tr[data-index="0"] .layui-icon[lay-event="move"][data-direction="up"]').addClass('layui-disabled');
        tableView.find('tr[data-index="' + (res.data.length - 1) + '"] .layui-icon[lay-event="move"][data-direction="down"]').addClass('layui-disabled');
      }
    });

    table.render({
      elem: '#table2'
      , url: 'examples/json/table/demo1.json'
      , toolbar: '<div><b>表格2,url模式</b></div>'
      , page: {
        limit: 10
      }
      , scrollPos: 'fixed'
      , totalRow: true
      , maxHeight: 480
      , cellMinWidth: 80
      , cols: [[
        {field: 'id', hide: true}
        , {type: 'numbers'}
        , {field: 'username', title: '用户名'}
        , {field: 'email', title: '邮箱'}
        , {field: 'joinTime', title: '日期'}
        , {field: 'experience', title: '积分', totalRow: true}
        , {field: 'checkin', title: '迁入', totalRow: true}
        , {title: '操作', align: 'center', toolbar: '#barDemo'}
      ]]
      , done: function (res, curr, count) {
        var tableView = this.elem.next();
        tableView.find('tr[data-index="0"] .layui-icon[lay-event="move"][data-direction="up"]').addClass('layui-disabled');
        tableView.find('tr[data-index="' + (res.data.length - 1) + '"] .layui-icon[lay-event="move"][data-direction="down"]').addClass('layui-disabled');
      }
    });

    table.on('tool', function (obj) {
      var btnElem = $(this);
      var tableId = obj.config.id;
      var dataCache = table.cache[tableId];
      var dataIndex = obj.index;

      var btnEvent = obj.event;
      switch (btnEvent) {
        case 'move':
          if (btnElem.hasClass('layui-disabled')) {
            return;
          }
          var direction = btnElem.data('direction');
          var dataMove = dataCache.splice(dataIndex, 1);
          var indexNew = dataIndex + (direction === 'up' ? -1 : 1);
          dataCache.splice(indexNew, 0, dataMove[0]);
          table.renderData(tableId);
          setTimeout(function () {
            table.setRowChecked(tableId, {
              index: indexNew,
              selectedStyle: true
            })
          }, 0);
          break;
        default:
          break;
      }
    })
  });


</script>
</body>
</html>

好的,多谢指教,我试下 :blush:

这边尝试了下改缓存再渲染的形式,有点不大好去过滤树形数组。

采用隐藏行的形式,基本能实现,代码如下:

$('#btnSearch').click(function(){
    var keywords = $('#keywords').val(), tableId = 'menus';
    if(keywords){
        treeTable.expandAll(tableId,true);
        var $trList = menusTree.config.elem.next().find('.layui-table-main table tbody').children('tr');
        $trList.addClass('layui-hide');
        var soList = [];
        $trList.each(function(){
            var $this = $(this), index = $this.data('index'), flag = false;
            $this.children('td').each(function(){
                if($(this).text().indexOf(keywords) !== -1){
                    soList.push(index);
                    return flag = true;
                }
            });
            if (flag) $this.removeClass('layui-hide');
        });
        for (var j = 0; j < soList.length; j++) {
            var $tr = $trList.filter('[data-index="' + soList[j] + '"]');
            $tr.removeClass('layui-hide');
            var level = parseInt($tr.data('level'));
            // 联动子级
            $tr.nextAll('tr').each(function () {
                if (parseInt($(this).data('level')) <= level) return false;
                $(this).removeClass('layui-hide');
            });
            var $icon = $tr.find('.layui-table-tree-flexIcon i.layui-icon');
            if ($icon.hasClass('layui-icon-triangle-d')) treeTable.expandNode(tableId,{index:soList[j],expandFlag:false});
            // 联动父级
            $tr.prevAll('tr').each(function () {
                var num = parseInt($(this).data('level'));
                if (num < level) {
                    $(this).removeClass('layui-hide');
                    var $icon = $(this).find('.layui-table-tree-flexIcon i.layui-icon');
                    if ($icon.hasClass('layui-icon-triangle-r')) $icon.removeClass('layui-icon-triangle-r').addClass('layui-icon-triangle-d');
                    level = num;
                }
            });
        }
    }else{
        treeTable.renderData(tableId);
    }
});

但是这里有个问题,搜索后显示的结果,再调用展开方法时,隐藏的无需行也显示了出来。
期待官方在后期版本中能有更好的搜索解决方案!

有一个思路你试试看:将根据关键字搜索表格的处理提取出来封装成一个方法,在input修改的时候调用,在table的done中也要去调用一下,根据已有的关键词去做一下处理,然后展开的回调也要去处理一下,这样应该就可以做到想要“过滤”的效果

嗯嗯。我这边刚仔细参照了下,对上面代码作了调整,基本上是可以的了。

追加一个样式来单独控制搜索时隐藏行,不再用layui-hide来控制以区分expandAll方法引起的隐藏或显示
<style>.treeTable-filter-hide{display:none !important;}</style>
点击搜索按钮的触发过程
$('#btnSearch').click(function(){
    var keywords = $('#keywords').val(), tableId = 'menus';
    if(keywords){
        // 这里全部展开是为了将所有的子类行 html 化,便于下面遍历搜索
        treeTable.expandAll(tableId,true);
        // 再全部收起,防止在搜索的子类过多情况下,全展开不便查看
        treeTable.expandAll(tableId,false);
        var $trList = menusTree.config.elem.next().find('.layui-table-main table tbody').children('tr');
        $trList.addClass('treeTable-filter-hide');
        var soList = [];
        $trList.each(function(){
            var $this = $(this), index = $this.data('index');
            $this.children('td').each(function(){
                if($(this).text().indexOf(keywords) !== -1){
                    soList.push(index);
                    return false;
                }
            });
        });
        for (var j = 0; j < soList.length; j++) {
            var $tr = $trList.filter('[data-index="' + soList[j] + '"]');
            $tr.removeClass('treeTable-filter-hide');
            var level = parseInt($tr.data('level'));
            // 联动子级
            $tr.nextAll('tr').each(function () {
                if (parseInt($(this).data('level')) <= level) return false;
                $(this).removeClass('treeTable-filter-hide');
            });
            var $icon = $tr.find('.layui-table-tree-flexIcon i.layui-icon');
            if ($icon.hasClass('layui-icon-triangle-d')) treeTable.expandNode(tableId,{index:soList[j],expandFlag:false});
            // 联动父级
            $tr.prevAll('tr').each(function () {
                var num = parseInt($(this).data('level'));
                if (num < level) {
                    $(this).removeClass('treeTable-filter-hide');
                    var index = $(this).data('index');
                    var $icon = $(this).find('.layui-table-tree-flexIcon i.layui-icon');
                    if ($icon.hasClass('layui-icon-triangle-r')) treeTable.expandNode(tableId,{index:index,expandFlag:true});
                    level = num;
                }
            });
        }/**/
    }else{
        treeTable.renderData(tableId);
    }
});

以上基本能实现了,还是希望官方能整理下把搜索的方法封装进去。

Niaho 任务状态待办的 修改为已完成
贤心 添加了
 
精华
标签
贤心 添加了
 
常见
标签

登录 后才可以发表评论

状态
负责人
里程碑
Pull Requests
关联的 Pull Requests 被合并后可能会关闭此 issue
分支
开始日期   -   截止日期
-
置顶选项
优先级
参与者(2)
8919371 niaho168 1695527144 627027 sun zoro 1578929630
JavaScript
1
https://gitee.com/layui/layui.git
git@gitee.com:layui/layui.git
layui
layui
layui

搜索帮助

53164aa7 5694891 3bd8fe86 5694891