4

I am using the Datatables library together with a visualforce page to create a funky table but I am having funky issues to get ti running.

Basically I have a button that will query the Salesforce database and refresh the table with the new results (this is because I try to limit as much as possible the number of items returned to maximize performance).

When this happens the filter function on the .keyup event of the th header does not work anymore. I tried changing the event handler function to use .live('keyup', function { BUT no luck, it still does not work.

I AM A VERY VERY INEXPERIENCED NOOB IN JS and jQuery, so please mind my mistakes and assist if you would like to.. below is the script that is not working:

    <script type="text/javascript" charset="utf-8">
    var theTable;
    $j = jQuery.noConflict(); 
    $j(document).ready(function() {
        theTable = loadDataTables();
            $j("th input").live('keyup', function () {
            /* Filter on the column (the index) of this element */
        theTable.fnFilter( this.value, $j("th input").index(this)+1 );
        });

    }); 

    function loadDataTables() {
        var vTable = $j("table[id$='ProductsTable']").dataTable({
        "bSort": false,
        "bJQueryUI": true,
        "bPaginate": true,
            "bScrollCollapse": false
        });
        $j("div[id$='_info']").hide();
        return vTable;
    }
</script>

IT works just fine before I click on the UI button and repopulate the table, after that the filter function no longer does anything.

UPDATED WITH SUGGESTED CHANGES BUT STILL NOT WORKING SEE CODE BELOW:

<script type="text/javascript" charset="utf-8">
var theTable;
$j = jQuery.noConflict(); 
$j(document).ready(function() {
    theTable = loadDataTables();
    bindColFilter(); 
} ); 

function loadDataTables() {
    var vTable = $j("table[id$='ProductsTable']").dataTable({
    "bSort": false,
    "bJQueryUI": true,
    "bPaginate": true,
    "bScrollCollapse": false
    });
    $j("div[id$='_info']").hide();

    return vTable;
}
function bindColFilter() {
    alert(theTable);

    $j("th input").keyup(function () {
        theTable.fnFilter( this.value, $j("th input").index(this)+1 );
    });
}  

VISUALFORCE PAGE BUTTON:

<apex:pageBlock title="Products available for selection" id="ProductsBlock" >
<apex:CommandButton value="Search by filters"  action="{!doSearch}" rerender="ProductsBlock" status="loadStatus" oncomplete="bindColFilter();" />
<apex:actionStatus startText="Performing search" style="font-weight:bold;color:#c00;text-align:center;" id="loadStatus"></apex:actionStatus>
    <apex:pageBlockTable value="{!PBEs}" var="p"  id="ProductsTable" rules="col" >

        <apex:column >
            <apex:commandButton action="{!addOLI}" value="Add"  rerender="OppLinesContainer">
                 <apex:param name="mCurrPBEID" value="{!p.id}" assignTo="{!mCurrPBEID}"/>
            </apex:commandButton>
        </apex:column>
2
  • As of jQuery 1.7, the .live() method is deprecated. Use .on() to attach event handlers.
    – Sami N
    Commented Mar 19, 2013 at 7:05
  • 1
    place you event handler code in loadDataTables function
    – Pratik Bhatt
    Commented Mar 19, 2013 at 7:29

1 Answer 1

4

Whole table is destroyed and replaced with fresh pure HTML from the server when you rerender it. So you have couple of options:

  1. use "oncomplete" event to "redecorate" the table as per answer given in the duplicate question (Jquery event handler does not fire after Visualforce table refresh)
  2. Include the decorating code in same part of the page as the table (for example encompassing page block) so it'll be executed every time:

    <apex:pageBlock id="block>
        <apex:dataTable id="ProductsTable">
            ...
        </apex:dataTable>
        <script type="text/javascript">
            loadDataTables();
        </script>
    </apex:pageBlock>
    
  3. Really use "live" events (as per Sam's comment - "on" should be used if you have new jQuery.

I'd say the first version is most clean (doesn't mix data and code flying back from the server every time and I'm also not a fan of having <script> tags sprinkled across whole document. on() might lead to interesting unwanted results if your page grows and starts to operate on several tables for example (also I'm not sure if it's not using a bit more memory).

2
  • Thank you for your quick reply, I have tried to add a oncomplete="bindColFilter();" parameter to the commandbutton executing the table refresh but still no luck, the method gets called the first time and it works fine since I tried a filter. Then when the button is pressed the alert is once again shown so the method gets called on the oncomplete event, BUT no filterring, the binding does not seem to be happening.I have added updated code to the question as per your instructions: Commented Mar 19, 2013 at 9:16
  • 2
    I am not allowed to answer my own question yet (noobs can't do this until 8 hrs after publishing). BUT following Pratiks advice (adding the binding code inside the loadDatatables() js method and calling that from the buttons oncomplete event, it works GREAT!!! THANK YOU ALL FOR YOUR FAST AND SMART RESPONSES, IT HELPED ME GET THROUGHT THIS ISSUE. I WILL POST THE CODE THAT WORKS WHEN THE SYSTEMS ALLOWS ME TO SO IT MAY HELP SOMEONE ELSE Commented Mar 19, 2013 at 9:39

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .