Search code examples
javascriptjquerytablesorter

updateCache for jquery.tablesorter iterates through the visible <tbody> rows when not all data is visible


I need to update the cache with the config I pass in, and not use the visible data as the length to loop through since not all data is within the DOM since I have it in my own custom pager component.

Im filtering the table and each time I filter it I update the tablesorter by running $(table).trigger('update') so that the user can sort their filtered list (the full entire list shows in the dom after each filter)

the issue comes in when they reset their sort and go back to the starting state.

when at the starting state only a few of the rows show (in a custom pager component)

I was reading the api docs on https://mottie.github.io/tablesorter/docs/index.html and it says for the pager widget it uses the updateCache since not all of its data is within the DOM at a time (kind of like my use case here).

But when I went and read the code of what 'updateCache' is doing, even though it allows you to pass in a custom config to use to set to, it iterates through the number of items within the

for ( tbodyIndex = 0; tbodyIndex < $tbody.length; tbodyIndex++ ) {

Im trying to see if I can manually update the internal cache with data THAT IS NOT PRESENT in the table. Iterate through the config passed in (i am saving the config off with a lodash deep copy so I can use this starting config later to set back to but its not working...yet)

api docs say to use $.tablesorter.updateCache( config, callback, $tbodies ); but its not working for me as my tbody data is not all in the DOM

I thought thats what this updateCache was for in the first place :/

thanks for your time!


Solution

  • Just gonna leave this here...

    Unfortunately, I had to edit the tablesorter source code to bind to my own custom event and in that event do what I wanted

    I was invoking my own callbacks after each filter and would do

    $(table).trigger('update')
    

    after each filter to allow the user to sort the filtered list

    but when they closed the search and was done/reset to the first page... since not all elements were in the DOM I needed to programatically update the cache to tell it what it should be (in this case the full list of the table data from starting out from the server - my pager is added after document is ready)

    in my case the cache should be reset back to its starting state when the init block runs basically

    i have some code in this widget (with enclosedGlobal set to {} in the scope to use) to backup/set the starting config for when the table first starts out so we can reset the cache back to it later programatically

    $.tablesorter.addWidget({
        id: 'sortStuff',
        init: function(table, thisWidget, config, widgetOptions) {
    
        },
        format: function(table, config, widgetOptions, initFlag) {
    
          if(initFlag === true) {
              enclosedGlobal[table.id] = {
                  startingConfig: cloneDeep(config),  //use lodash's cloneDeep to deep copy object so when the config is mutated it doesnt mutate our saved off starting config
                  startingReference: config           //will be helpful to mutate internal config reference the tablesorter logic used (specifially `initSort`)
              }
          }
    
        }
    
    
    
    
    })
    

    then later in my custom filterEnd callback I invoke when the user is done with the search and they are reset back to the first page in the table

    var nextConfig = typeof enclosedGlobal !== 'undefined' && enclosedGlobal.hasOwnProperty(table.id) && enclosedGlobal[table.id].hasOwnProperty('startingConfig') ? cloneDeep(enclosedGlobal[table.id].startingConfig) : {},
        startingReference = typeof enclosedGlobal !== 'undefined' && enclosedGlobal.hasOwnProperty(table.id) && enclosedGlobal[table.id].hasOwnProperty('startingReference') ? enclosedGlobal[table.id].startingReference : null
        callback = function() {
            //do anything after the custom event logic runs 
        };
    
    $(table).trigger('SOMENAMESPACE-myCustomEvent', [nextConfig, startingReference, callback]);
    

    Now for the jquery.tablesorter code modifications

    Look somewhere for the bindMethods function with the string:

    "sortReset update updateRows updateAll updateHeaders addRows updateCell updateComplete sorton appendCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave "
    

    and add your custom event you are triggering here.

    after that code you should see code something like

    .bind("updateCache"...
    
    )
    

    add your binding after that mimicking the code around it

    .bind('SOMENAMESPACE-myCustomEvent' + namespace, function(e, nextConfig, startingReference, callback) {     
        e.stopPropagation();
        customCodeToRun(ts, this.config, nextConfig, startingReference, callback);
    })
    

    depending on if the code youre editing is minified lawl the first parameter could change. in the unminified code the first paramter was ts but in my case the minification turned ts into L so youd have to pay attention here and namespace in my case was changed to t

    also you need to implement customCodeToRun for it to use. heres what i put in mine pretty much

    function customCodeToRun(ts, currentConfig, nextConfig, startingReference, callback) {
        startingReference = $.extend(currentConfig, nextConfig);  //use $.extend to preserve the object's memory reference and mutate that objects memory/value so that the underlying internal tablesorting logic can use the updated values being set within the config from within `nextConfig`
        if(typeof callback === 'function') {
            callback();
        }
    
    }
    

    I had a lot of issues coming from react where you copy and never mutate objects so be careful to try to understand the memory references. This is what made the cloneDeep so tricky and weird to me at first since I had to do that to properly protect my object state from being mutated by future updates. I used the $.extend logic to keep the same memory reference but use the cloned stored off state.

    last part you need to add to the event bindings for when cleaning up the event listeners. search through the jquery.tablesorter source code one last time and add to the string

    "sortReset update updateRows updateAll updateHeaders updateCell addRows updateComplete sorton appendCache updateCache applyWidgetId applyWidgets refreshWidgets removeWidget destroy mouseup mouseleave "+"keypress sortBegin sortEnd resetToLoadState "
    

    the same custom event you made earlier except this part of the logic removes the event listeners for that specific event. I think its in the internal destroy method logic, in our example case here the string would be changed to (just to be nice)

    "sortReset update updateRows updateAll updateHeaders updateCell addRows updateComplete sorton appendCache updateCache SOMENAMESPACE-myCustomEvent applyWidgetId applyWidgets refreshWidgets removeWidget destroy mouseup mouseleave "+"keypress sortBegin sortEnd resetToLoadState "
    

    can you find it in there? wheres waldo...

    hope it helps good luck cheers