5

I tried callingsetFilter function on my Tabulator tree structure, in order to filter out items. It seems to only filter out top parents. Any idea how to make this work for any level (any children or parents)? http://tabulator.info/docs/4.1/tree doesn't say much about how filtering works.

Function

table.setFilter('id', '=', 214659) is not returning anything...

Tree structure

[
   {
      "level":0,
      "name":"word1",
      "id":125582,
      "_children":[
         {
            "level":1,
            "name":"word6",
            "id":214659
         },
         {
            "level":1,
            "name":"word7",
            "id":214633
         },
         {
            "level":1,
            "name":"word2",
            "id":214263,
            "_children":[
               {
                  "level":2,
                  "name":"word8",
                  "id":131673
               },
               {
                  "level":2,
                  "name":"word9",
                  "id":125579
               },
               {
                  "level":2,
                  "name":"word10",
                  "id":125578
               },
               {
                  "level":2,
                  "name":"word4",
                  "id":172670,
                  "_children":[
                     {
                        "level":3,
                        "name":"word13",
                        "id":172669
                     },
                     {
                        "level":3,
                        "name":"word14",
                        "id":174777
                     },
                     {
                        "level":3,
                        "name":"word5",
                        "id":207661,
                        "_children":[
                           {
                              "level":4,
                              "name":"word15",
                              "id":216529
                           },
                           {
                              "level":4,
                              "name":"word16",
                              "id":223884,
                              "_children":[
                                 {
                                    "level":5,
                                    "name":"word17",
                                    "id":223885,
                                    "_children":[
                                       {
                                          "level":6,
                                          "name":"word18",
                                          "id":229186,
                                          "_children":[
                                             {
                                                "level":7,
                                                "name":"word19",
                                                "id":219062
                                             },
                                             {
                                                "level":7,
                                                "name":"word20",
                                                "id":222243
                                             }
                                          ]
                                       }
                                    ]
                                 }
                              ]
                           }
                        ]
                     }
                  ]
               },
               {
                  "level":2,
                  "name":"word3",
                  "id":214266,
                  "_children":[
                     {
                        "level":3,
                        "name":"word11",
                        "id":216675
                     },
                     {
                        "level":3,
                        "name":"word12",
                        "id":216671
                     }
                  ]
               }
            ]
         }
      ]
   }
]
konichiwa
  • 532
  • 1
  • 5
  • 23
  • Can't you filter the data outside of the tabulator and just render the new data? Didn't work before with this, I'm just asking. Taking into account it's still javascript it should work – Sabbin Apr 06 '20 at 15:37
  • What would be an efficient way? I have around 1M records in my JSON. – konichiwa Apr 06 '20 at 15:45
  • Iteration and recursive functions... it depends on what is the filter condition and what you want to return. – Sabbin Apr 06 '20 at 15:52
  • Any record that has `id` equal to 214659, for example... – konichiwa Apr 06 '20 at 15:53

2 Answers2

3

After a little searching found out an extension for lodash library called deepdash which has deep level filtering and it works quite well.

You will have 2 new dependencies but I think it will serve your purpose. Check the documentation on how to install them here

In the snippet here you can see in the log the results. I made a sandbox also here

This is for a list of ids, one or more.

If you need only for one value change the conditional. return _.indexOf(idList, value.id) !== -1; to return id===value.id; where id is your id variable

Also after looking at the documentation from Tabulator, the have only one level filtering, even if you write your own custom filter it wouldn't help, because it expects a bool value to render the row or not. But only for the first level, so if the parent is not what you look for the child will be ignored. The only option for you is to filter the data outside the Tabulator.

const data = [
  {
    level: 0,
    name: "word1",
    id: 125582,
    _children: [
      {
        level: 1,
        name: "word6",
        id: 214659
      },
      {
        level: 1,
        name: "word7",
        id: 214633
      },
      {
        level: 1,
        name: "word2",
        id: 214263,
        _children: [
          {
            level: 2,
            name: "word8",
            id: 131673
          },
          {
            level: 2,
            name: "word9",
            id: 125579
          },
          {
            level: 2,
            name: "word10",
            id: 125578
          },
          {
            level: 2,
            name: "word4",
            id: 172670,
            _children: [
              {
                level: 3,
                name: "word13",
                id: 172669
              },
              {
                level: 3,
                name: "word14",
                id: 174777
              },
              {
                level: 3,
                name: "word5",
                id: 207661,
                _children: [
                  {
                    level: 4,
                    name: "word15",
                    id: 216529
                  },
                  {
                    level: 4,
                    name: "word16",
                    id: 223884,
                    _children: [
                      {
                        level: 5,
                        name: "word17",
                        id: 223885,
                        _children: [
                          {
                            level: 6,
                            name: "word18",
                            id: 229186,
                            _children: [
                              {
                                level: 7,
                                name: "word19",
                                id: 219062
                              },
                              {
                                level: 7,
                                name: "word20",
                                id: 222243
                              }
                            ]
                          }
                        ]
                      }
                    ]
                  }
                ]
              }
            ]
          },
          {
            level: 2,
            name: "word3",
            id: 214266,
            _children: [
              {
                level: 3,
                name: "word11",
                id: 216675
              },
              {
                level: 3,
                name: "word12",
                id: 216671
              }
            ]
          }
        ]
      }
    ]
  }
];

const idList = [214659];
const found = _.filterDeep(
  data,
  function(value) {
    return _.indexOf(idList, value.id) !== -1;
  },
  { tree: true, childrenPath: '_children' }
);

console.log(found);
<script src="https://cdn.jsdelivr.net/npm/lodash/lodash.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/deepdash/browser/deepdash.min.js"></script>
<script>
  deepdash(_);
</script>
Sabbin
  • 2,215
  • 1
  • 17
  • 34
0

Here is a recursive function that will find the parent and/or children matching a condition.

In this example, the parent item will always be displayed if a child item is a match - even if the parent itself is not a match - but you can easily adjust the code to your needs by tuning the test in the for loop.

var filterTree = function (data, filter) {
   if (data['_children'] && data['_children'].length > 0) {
      for (var i in data['_children']) {
         return data[filter.field] == filter.value || filterTree(data['_children'][i], filter);
      }
   }

   return data[filter.field] == filter.value;
};

Call this function as a custom filter callback:

table.setFilter(filterTree, {field:'myfield', type:'=', value:'myvalue'});

Note that this is just example code that focuses on the logic of filtering a tree recursively. The above works only for the '=' comparison.

In a real situation, you will have to implement more code to handle all other operators supported by tabulator, as dynamic operator assignment is not possible in Javascript. You could maybe consider eval() but that's another story.

More info about dynamic operator assignment here: Are Variable Operators Possible?

Here is an example of implementation handling all tabulator operators:

// Operators
var compare = {
    '=': function(a, b) { return a == b },
    '<': function(a, b) { return a < b },
    '<=': function(a, b) { return a <= b },
    '>': function(a, b) { return a > b },
    '>=': function(a, b) { return a >= b },
    '!=': function(a, b) { return a != b },
    'like': function(a, b) { return a.includes(b)}
};

// Filter function
var filterTree = function (data, filter) {
    if (data['_children'] && data['_children'].length > 0) {
        for (var i in data['_children']) {
            return compare[filter.type](data[filter.field], filter.value) || filterTree(data['_children'][i], filter);
        }
    }

    return compare[filter.type](data[filter.field], filter.value);
};

// Set a filter. The operator can now be provided dynamically
table.setFilter(filterTree, {field:'myfield', type: '>=', value:'myvalue'});