External Tree checkbox filtering for exclusive rows for grid

Scenario: Dhtmlx 5 tree with Dhtmlx 7 grid

I am trying to filter only the checkbox items in a large dataset after it has been populated initially on page load.

Right now if I select a few check boxes it filters what was checked…but when i want to filter on the actual grid it includes the original 32k rows behind the scenes even though the grid view only shows the let’s sat 1200 rows returned from the checkboxes. Is it possible to have a grid only filter what was populated by the checkboxes? For example if I filter out a few rows with checkboxes and I know there is no value in these rows but is in the original rows…it filters out those rows which is very confusing. So, I looked through the documents and it seemed the add/smartfilter is what i needed…well, it does not break anything…but it has the same results as original code.

Is it possible to do what I am asking? - Please advise - thanks

  1. grid on load is populated by json data (variable computers) from external file (32k rows)

    var computer_grid = new dhx.Grid(“comp_grid”, {
    columns: [
    { width: 150, id: “unit”, header: [{ text: “Unit” },{ content: “selectFilter” }] },
    { width: 150, id: “computer”, header: [{ text: “Computer”},{ content: “inputFilter” }] },
    { width: 225, id: “model”, header: [{ text: “Model”},{ content: “selectFilter” }] },
    { width: 125, id: “serial”, header: [{ text: “Serial”},{ content: “inputFilter” }] }
    ], data: computers
    });

  2. There is a tree object that has a list of checkbox ids that can be used to filter grid externally:

    myTree_Tab_02_Cell_A = myLayout_Tab_02_Cell_B_A1.cells("a").attachTree();
    myTree_Tab_02_Cell_A.enableSmartXMLParsing(true);
    myTree_Tab_02_Cell_A.enableCheckBoxes(1);
    myTree_Tab_02_Cell_A.enableThreeStateCheckboxes(true);
    myTree_Tab_02_Cell_A.enableTreeImages(false);
    myTree_Tab_02_Cell_A.enableTreeLines();      
    myTree_Tab_02_Cell_A.load(xml_AOR_Tree);
    
  3. There is an oncheck event for the tree in which uses a loop to iterate checkbox values to filter grid:

      myTree_Tab_02_Cell_A.attachEvent("onCheck", 
                                  function(id,state)
                                     { 
      computer_grid.data.filter(function(item){ for(var i=0;i<a1.length;i++) 
                                                  { 
     						if(item.unit.toString().indexOf(a1[i])!=-1) return true; 
                                                  }     
                                                  return false;
                                             }, { add: true,    smartFilter: true   })   });

I’m hoping I understand correctly what you’re trying to do, let me see if restating it sounds correct:

  1. Grid has 32000+ rows of data loaded into grid.data object.
  2. When items are checked in the tree, it applies a filter to the grid.data object, so only corresponding rows are shown.
  3. When you try to filter the grid directly (through header content item, such as inputFilter?) it’s returning rows based on all the original rows, not the items already filtered.

If this is the correct situation, then I think the issue you’re running into is that filtering via header rows ignores/replaces existing filter settings and only combines the filter rules set within the headers. Unless a setting for the grid already exists that I don’t know about, changing this behavior involves a development change, and I would expect that level of change to take quite a while.

I see 2 options for now:

First, you could load the data into a standalone object, and then repopulate the grid with only the items as filtered by the Tree. Then filtering the grid directly would only operate on the rows that meet the filter rules imposed by the Tree. This involves some memory overhead from maintaining one or more data objects, but it may take less processing to do the grid filtering on fewer data rows.

The second option (maybe) is to use the filterChange event of the Grid. You’d have to do some tests to see if it fires before or after the filter is applied to the Grid. If it’s after, you could use that event to call the filtering function currently being run by the oncheck event of the Tree. In effect, you would let the Grid run its own filter, and then (using the “add” and “smartFilter” settings) you would apply the extra filtering based on the checkbox status of the Tree.

If the Tree isn’t expected to change much (i.e., it’s set once after the page loads, it doesn’t change and all other filtering is done via the grid), I would probably choose to go with the first option because you wouldn’t have to keep reapplying the same filter over and over on thousands of rows; that could be a significant performance impact. But that all depends on how you use the page, so I leave that to your determination.

kcasarez,

Thank you for taking the time to reply with a detailed message. Yes…I imagine it would take time to develop a feature that mimics Excel filtering capabilities…I sorta went with option 1. It’s a 5.x tree object in conjunction with 7.x grid …so using getAllChecked() to stuff into a variable then iterating it allowed me to return json rows based on the array name compare to the tree name withinn the for loop…then used 7.x grid.data.parse(data_set_03) to populate rows

Yes, a very slight performance hit with all checks (approx 300 - if all checked) and then iterating 300 times against json (stringify) I presume would do that. Probably a better way…but it’s literally less than a second in timing but the delay from checking a checkbox and oncheck event/rendering is a tad noticeable but certainly acceptable.

That’s with a 5.x tree…I find the 5.x version was easier to pick up than on it’s big brother 7.x…

I find it hard to google terms to pick up on 7.x…a lot are for 5.x…and I have gone through 7.x docs … but I cannot seem to find how to iterate a 7.x grid rows…

For example I have a metrics grid that displays x amount of units…to iterate the rows and grab the 1st column/row value (unit) … this iteration would populate another grid for these units widgets which are in a json file (local source) … i see you guys have a datacollection and parse values … but I’m used to 5.x and don’t see any comparable solutions…hopefully i explained it well enough…thanks for your help

I found a FindAll method that does what i need it to do except it gets all rows (not filtered/visible) only…

sdc_grid.data.findAll(function (item) {

           alert(item.unit);  // grabs all rows...not just visible
        
    });

Got it to work by getting row total in grid with data.getLength() … set up a loop and in the loop i converted each row to a json string (stringify) then to get the value i neded (unit) …I used JSON.parse

for (i = 0; i < sdc_grid.data.getLength(); i++) 
  {

    data = sdc_grid.data.getItem(sdc_grid.data.getId(i))

    var json = JSON.stringify(data)
    var obj =  JSON.parse(json)
    var unit = obj.unit;
    
   // ...
 };

Please lookover…if a better solution…always wanting to learn more efficient code - thanks!

ADD:

This is maddening…I didn’t notice the issue immediately but finally realized after a few attempts of loading fresh data to a grid from either a tree checkbox or a list of row values from a another grid … it appends “ghost” rows to my results. Meaning…after I apply a “custom” filter from a tree or another grid…in the grid i added rows to is perfectly fine if in scrollable area…but if you look in the header filters…it is clearly adding cached or old data to the grid…although i cannot see it in pane…do i need a 5.x equivalent like grid.clearAll(); after each time i select checkboxes and or other grid? why is it showing up in the header but not the body?

Please advise - thanks

I suspect it’s showing items in the header that exist in the data set, but are being hidden by a filter after they’re added to the grid. Filtering within the grid only “hides” the rows, making them not display, but it doesn’t remove them from the data set. The header has to show values from all the rows (even filtered rows) or you wouldn’t be able to select a different filtering value once you had filtered the rows the first time (on any grid, not just specifically your situation).

DHX 7 doesn’t have a clearAndLoad() function like DHX 5 did for the grid; instead , whenever you’re loading fresh data into the grid, you should probably do a grid.data.removeAll() just to make sure old data isn’t retained.

It may be worth some effort to figure out the DHX 7 tree; it stores the data in JSON natively, so you don’t have to stringify every row. And it actually uses the same data structure (DataCollection) that Grid uses, so a lot of the functions are the same. That may make it easier instead of switching back and forth between versions. I’d be happy to try helping you get that converted, if you like.

Also, looking at your code… I think you’re way over-processing the data to get your value. I’m not quite clear on what you’re doing with the second grid; is this an alternative to the Tree, or in addition to it? At any rate, if you’re using a DHX 7 grid, the data is already JSON, so you don’t need to do a bunch of conversions on it. You can simplify this:

for (i = 0; i < sdc_grid.data.getLength(); i++) 
  {

    data = sdc_grid.data.getItem(sdc_grid.data.getId(i))

    var json = JSON.stringify(data)
    var obj =  JSON.parse(json)
    var unit = obj.unit;
    
   // ...
 };

to:

for (i = 0; i < sdc_grid.data.getLength(); i++) 
  {
    var obj = sdc_grid.data.getItem(sdc_grid.data.getId(i))
    var unit = obj.unit;
    
   // ...
 };

I also think forEach() takes filtering into account (not 100% sure, though, so you’d have to test it) so you could reduce even farther to this:

sdc_grid.data.forEach(function(obj){
    var unit = obj.unit;

    // ...
});