function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
John NeffJohn Neff 

Sortable HTML Table in a VF Page?

Hello, 

I am trying to make an HTML table inside of a VF page sortable - but I am having some trouble. 

I am using this sample as a template: http://www.kryogenix.org/code/browser/sorttable/

And if I create a dummy page with static, dummy data this works like a charm.  Howeever if I apply this to a VF page that retruns data from a controller it doesn't work. 

When I click on a table header, the alternating "up/down" arrows appear, but the data doesn't budge.  Is there something that I need to add to my controller to make this work?

Here is my page: 
 
<script src="{!URLFOR($Resource.sorttable)}"> </script>
<meta charset="utf-8" />
<title>R2M PIPELINE</title>
<link rel="stylesheet" type="text/css" href="{!URLFOR($Resource.GUIstyle)}" media="all" />
</head>
<body>
    <div id="header">
            <div id="logo">
                <a href="index.html"><img src="{!URLFOR($Resource.Logo)}" alt="" /></a>       
            </div>
<ul>
    <li><a href="apex/GUIHome"><span>Gene</span></a></li>
                <li><a href="/apex/HappeningNow"><span>Happening Now</span></a></li>
                <li><a href="/apex/ClientDelivery"><span>Client Delivery</span></a></li>
                <li><a href="/apex/MediaCash"><span>Media Cash</span></a></li>
                <li><a href="/apex/ROIREVENUE"><span>ROI and Revenue</span></a></li> 
                <li><a href="/apex/PRODUCTION"><span>Production</span></a></li>    
                <li><a href="/apex/SalesActivity"><span>Sales Activity</span></a></li> 
                <li><a href="/apex/PIPerformance"><span>PI Performance</span></a></li>
                <li><a href="https://na2.salesforce.com/"><span>Salesforce Home</span></a></li> 
            </ul>
  </div>
    <div id="body">
        <div class="about">
            <h1>R2M Pipeline</h1>
            <div>
            
           <c:PipelineNav />


 <apex:repeat value="{!campaigns}" var="camp">

    <apex:form >
    <apex:pageBlock title="{!camp}" mode="inlineedit">
        <table cellpadding="5" style="border-collapse: collapse;table-layout:fixed" width="1080" border="1" class="sortable" >
                
                <thead>
                <tr>
                              <th style="background-color: #C6D4D4; color: #040404" width="100">
                        <b>Opportunity Name</b>
                    </th>
                    <th style="background-color: #C6D4D4; color: #040404" width="100">
                        <b>Company Name</b>
                    </th>
                    <th style="background-color: #C6D4D4; color: #040404" width="80">
                        <b>Contract Sent</b>
                                   
                    
                    </th>
                     <th style="background-color: #C6D4D4; color: #040404" width="50">
                        <b>Days Idle</b>
                    </th>
                                 
                    <th style="background-color: #C6D4D4; color: #040404" width="70">
                        <b>Created</b>
                    </th>
        <th style="background-color: #C6D4D4; color: #040404" width="450">
                        <b>Next Step</b>
                    </th>
                  
                    <th style="background-color: #C6D4D4; color: #040404" width="50">
                        <b><apex:commandLink reRender="button" onclick="window.open('/apex/Probability_Guide','','width=500,height=300')" id="button">Prob%</apex:commandLink></b>
                    </th>
                    <th style="background-color: #C6D4D4; color: #040404" width="100">
                        <b>Owner</b>
                    </th>
                    <th style="background-color: #C6D4D4; color: #040404" width="100">
                        <b>Stage</b>
                    </th>
                
                </tr>
                </thead>
                
                 <apex:repeat value="{!Opty}" var="cs"> 
                 
                  <apex:outputPanel rendered="{!IF(camp=cs.Vert_Med__c,true,false)}" >
                  <tbody>
                      <tr>
                                  
                            <td width="100">
                                <a href="https://na2.salesforce.com/{!cs.id}">{!cs.name}</a>
                            </td>  
                              <td width="100">
                                {!cs.Company_Name__c}
                            </td> 
                                <td width="80">
                            
                               <apex:outputField value="{!cs.Contract_SENT__c}" >
                                     <apex:inlineEditSupport event="ondblclick" showOnEdit="saveButton, cancelButton" />
                                </apex:outputField>
                            </td>
                          
                           
                            <td width="50">
                                {!cs.Days_Since_Last_Modified__c}
                            </td>
                            <td width="70">
                                 {!MONTH(DATEVALUE(cs.CreatedDate))}/{!DAY(DATEVALUE(cs.CreatedDate))}/{!YEAR(DATEVALUE(cs.CreatedDate))}
                            </td>
                            
                            <td width="450">
                                <apex:outputField value="{!cs.Next_Step__c}" >
                                     <apex:inlineEditSupport event="ondblclick" showOnEdit="saveButton, cancelButton" />
                                </apex:outputField>
                            </td>
                
                           
                             <td width="50">
                                <apex:outputField value="{!cs.Probability}" >
                                     <apex:inlineEditSupport event="ondblclick" showOnEdit="saveButton, cancelButton" />
                                </apex:outputField>
                            </td>
                            <td width="100">
                                {!cs.Owner_Name__c}
                            </td>
                            <td width="100">
                                {!cs.StageName}
                            </td>
                          
                        </tr>
                     </tbody>
                      </apex:outputPanel>
                     </apex:repeat>
                     </table>
                     
                     <apex:commandButton action="{!saveOp}" value="Update Opptys"/>  
    </apex:pageBlock>
    </apex:form>
            <br/>
  </apex:repeat>
           
                          </div>
            <div>
                    
             </div>
            <div> </div>
        </div>
    </div>
         <div id="footer">
            <div>
                <div>
                    <h3></h3>
                    <ul>
                        <li></li>                
                        <li></li>
                    </ul>           
                </div>      
                <div>
                    <h3></h3>
                    <ul>
                        <li></li>                
                        <li></li>
                    </ul>           
                </div>  
                <div>
                    <h3></h3>
                    <ul>
                        <li></li>                
                        <li></li>
                    </ul>           
                </div>  
                <div>
                    <h3></h3>
                    <ul>
                        <li></li>                
                        <li></li>
                    </ul>           
                </div>  
                <div>
                    <h3>Social</h3>
                    <a class="facebook" href="https://www.facebook.com/pages/Ring2Media-INC/845391462194555" target="_blank">R2M Facebook</a>     
                    <a class="twitter" href="https://twitter.com/ring2media" target="_blank">R2M Twitter</a>
                </div>  
            </div>
            <div>
                            </div>
        </div>
        <style>

             .odd {

              background-color: #A4A4A4;

                }

             .even {

             background-color: #E6E6E6;

                }

            </style>
    </body>            
                  


</html>

And here is my controller: 
 
public with sharing class QualOpController
{

public List <Opportunity> Opty {get;set;}
public list<String> campaigns {get;set;}

public PageReference saveOp(){
    UPDATE Opty;
    return null;
    }

 public String getName(){
        return 'QualOpController';
        }

public void load() 
{
  campaigns= new List<String>();
  Opty = [Select id, name, CreatedDate, StageName, Vert_Med__c, Company_Name__c, Next_Step__c, Vertical__c, Weeks_Live__c, Days_Since_Last_Modified__c, Contract_SENT__c, NextStep, LeadSource, Probability, Spend_Last_Week__c, Spend_Last_30_Days__c, Owner_Name__c, Revenue_All_Time__c from Opportunity WHERE Pipeline_Oppty__c = TRUE ]; 
  
  Set<String> campaignSet = new Set<String>();
  for (Opportunity j : Opty)
      campaignSet.add(j.Vert_Med__c);
      
      for (String campaign : campaignSet) 
      {
            campaigns.add(campaign);
      }
      campaigns.sort();
    }
}

Is it possible to achieve what I am trying to accomplish with this method?

Thanks, 

John
Best Answer chosen by John Neff
Chris  ByromChris Byrom
I have not used this library before, but I would check two things. First you have the <tbody> tag inside of your repeater. This looks like it is creating each row (<tr>) with its own body. You only need one <tbody>, so put that outside of your repeater. You also seem to be putting an <apex:outputPanel> around each row to show it or hide it. This will create a span tag around each row, along with the current <tbody>, which will probably break the sorter. It is going to be looking for table rows to sort <tr>, and these extra tags are probably preventing it from working.

The next thing I would look at is the Javascript Console in your browser. Are you getting any errors when performing your sorts? You may not be, because it may not find anything to sort due to what I covered above. Again, I have never used this library, but this would be my first try to get it working. Also, look at the generated code, to see what else is in there that may be interfering with your sorting library.

I would strip this down to its basics to see where the problem is. The sample in this doc, might be a good place to start, to see if you can get the sorting working.

https://developer.salesforce.com/docs/atlas.en-us.pages.meta/pages/pages_compref_repeat.htm

All Answers

Chris  ByromChris Byrom
I have not used this library before, but I would check two things. First you have the <tbody> tag inside of your repeater. This looks like it is creating each row (<tr>) with its own body. You only need one <tbody>, so put that outside of your repeater. You also seem to be putting an <apex:outputPanel> around each row to show it or hide it. This will create a span tag around each row, along with the current <tbody>, which will probably break the sorter. It is going to be looking for table rows to sort <tr>, and these extra tags are probably preventing it from working.

The next thing I would look at is the Javascript Console in your browser. Are you getting any errors when performing your sorts? You may not be, because it may not find anything to sort due to what I covered above. Again, I have never used this library, but this would be my first try to get it working. Also, look at the generated code, to see what else is in there that may be interfering with your sorting library.

I would strip this down to its basics to see where the problem is. The sample in this doc, might be a good place to start, to see if you can get the sorting working.

https://developer.salesforce.com/docs/atlas.en-us.pages.meta/pages/pages_compref_repeat.htm
This was selected as the best answer
Jerun JoseJerun Jose
As Chris mentioned, move the <tbody> tags outside of the repeater. If you need to use the outputpanel only for render conditions, try using apex:outputpanel layout="none" - this will not create any HTML elements while rendering the page.
John NeffJohn Neff
Thank you both very much - this information was very helpful and it did the trick!  I only wish that I could select two best answers - as the layout="none" and the moving of the tbody tags are what did it. 

Thank you so much!
John NeffJohn Neff
Is there any chance that you guys could help me get my inline edit support to work with this controller? 

I am trying to use:
 
public PageReference saveOp(){
    UPDATE Opty;
    return null;
    }

 public String getName(){
        return 'QualOpController';
        }

to update: 
 
Opty = [Select id, name, CreatedDate, StageName, Vert_Med__c, Company_Name__c, Next_Step__c, Vertical__c, Weeks_Live__c, Days_Since_Last_Modified__c, Contract_SENT__c, NextStep, LeadSource, Probability, Spend_Last_Week__c, Spend_Last_30_Days__c, Owner_Name__c, Revenue_All_Time__c from Opportunity WHERE Pipeline_Oppty__c = TRUE ];

in the controller above but I keep getting stuck!  I am about to pull my hair out!  Is it because I am querying opporyunities in a string and not a list?