2

Is there a way to implement horizontal and vertival scroll to a pageblocktable similar to the ones in ListViews?

Similar to ListViews means vertical scrolling is only for the data and not for header and header and body share the same horizontal scrolling .

I tried;

<script>
var idx = "{!$Component.myPb.displayTable}";
idx = idx +':tb'; // Get the body of page block table
document.getElementById(idx).style = "overflow:auto;height: 250px;";
</script>

But it is not helping.

Update: I tried the StickyTableHeader mentioned in Eric's Answer which is working great but only problem is if overflowing horizontally it miss-aligns the header and body

After Horizontal scroll enter image description here

After Horizontal-Vertical scrollenter image description here

3
  • You have two answers that took the time to provide you a solution yet you have not awarded the bounty. As it stand the bounty will not be awarded to anyone that took the time to help you. Can you please either select and answer, up vote the one that helped you most, or award the bounty?
    – Eric
    Nov 22, 2016 at 4:08
  • You were on 45 minutes ago. Can you let us know why you did not award the bounty so we can help you get this answered?
    – Eric
    Nov 22, 2016 at 5:00
  • Seems is because inside a container with fixed width. Either take it out of the container or see: github.com/jmosbech/StickyTableHeaders/issues/1 (goto March 30 2013 answer on)
    – Eric
    Nov 22, 2016 at 12:33

4 Answers 4

4

Quickest way to do this would be to use StickyTableHeaders. (Most reliable solution I have used) and provides the most standard like UI compared to other solutions. Datatables.net is also a great resource if you want to add search and filtering. I like it much better that jQuery data tables.

https://github.com/jmosbech/StickyTableHeaders

Here is a MVR code for you to try using a set height div and the Account object. I have to placed the JS in a static resource for this example.

<apex:page id="examplePage" standardController="Account" recordSetVar="acc">

    <apex:includeScript value="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"/>
    <apex:includeScript value="{!URLFOR($Resource.StickyHeaders)}"/>

    <style>
        .squeeze {
            overflow: auto;
            height: 200px;
        }
    </style>
    <apex:pageBlock>
        <apex:outputPanel layout="block" styleClass="squeeze">
            <apex:pageBlockTable id="pgb_table" value="{!acc}" var="a">
                <apex:column headerValue="Name" value="{!a.Name}"/>
            </apex:pageBlockTable>

            <script>
                $('[id$=pgb_table]').stickyTableHeaders({scrollableArea: $('.squeeze')});
            </script>
        </apex:outputPanel>

    </apex:pageBlock>

</apex:page>

Image on load

enter image description here

Image after scrolling a few

enter image description here

Horizontal scrolling should happen by default.

6
  • Hi Eric. Thanks for the answer. I will try it and let you know. Nov 20, 2016 at 13:20
  • @SaumyaRanjanSatapathy - How did it work for you??
    – Eric
    Nov 21, 2016 at 16:24
  • Eric, This api works great. Actually this is what I was looking for. Sorry for this late replay as I was stuck with some other issues. And sure I will add the bounty again and award it. Nov 22, 2016 at 7:53
  • Just one problem I am seeing with this api, when I set width of the table and then I scroll horizontally or vertically. I am updating the screenshot in the questions. Nov 22, 2016 at 7:55
  • @SaumyaRanjanSatapathy did you add any css??
    – Eric
    Nov 22, 2016 at 11:38
1

One easy way to implement this requirement is using Jquery datatable plugin. It will give you horizontal and vertical scrolling including many other functionality. Here is a sample Visualforce Page. Hope this helps.

 <apex:page standardController="Account" recordSetVar="accounts" >
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.3/jquery.min.js"></script>
    <script src="https://cdn.datatables.net/1.10.12/js/jquery.dataTables.min.js"></script>
    <style type="text/css">
        div.dataTables_wrapper {
            width: 800px;
            margin: 0 auto;
        }
    </style>    
    <apex:pageBlock id="thePageBlock" >
        <apex:pageBlockSection id="theSection">
            <apex:pageBlockTable value="{!accounts}" width="100%" var="acc" id="theTable" styleClass="opp-table">
                <apex:column value="{!acc.name}"/>
                <apex:column value="{!acc.AccountNumber}"/>
                <apex:column value="{!acc.AnnualRevenue}"/>
                <apex:column value="{!acc.Fax}"/>
                <apex:column value="{!acc.phone}"/>
                <apex:column value="{!acc.AccountSource}"/>
                <apex:column value="{!acc.BillingStreet}"/>
                <apex:column value="{!acc.BillingCity}"/>
                <apex:column value="{!acc.BillingState}"/>
                <apex:column value="{!acc.BillingPostalCode}"/>
                <apex:column value="{!acc.BillingCountry}"/>
                <apex:column value="{!acc.OwnerId}"/>
                <apex:column value="{!acc.ParentId}"/>                
            </apex:pageBlockTable>
        </apex:pageBlockSection>
    </apex:pageBlock>
    <script type="text/javascript">
        j$ = jQuery.noConflict();
        j$(document).ready(function () {
            j$('[id$=theTable]').DataTable( {
                "bSort" : false,
                "bPaginate": false,
                "bFilter": false,
                "bInfo": false,
                "scrollY": 200,
                "scrollX": true
            } );
        });  
    </script>    
</apex:page>

Screenshot:

enter image description here

1
  • Thanks Saroj. I tried Datatables jquery api. I liked its ui even more. But I was not able to bind the table buttons with the server side actions, like the next and previous buttons should invoke next() and preivious() of standard set controller. Even the page size, sorting and searching should go to controller and fetch the data instead of operating on the data that gets downloaded when the page loads. Could you help me doing that? Nov 20, 2016 at 13:19
0

StickyTableHeaders jquery api is definitely easy and concrete approach if your page do not over flow horizontally.

As my table had many columns and rows which made the container div overflow horizontally and vertically, so I switched to HTML tables.

SampeTable

<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css"></link>
<meta charset=utf-8 />
<title>Scroll Example</title>
  <style>
    .scroll-example {
      display: block;
      margin-right: 20px;
      width: 100%;
    }
    td {
        border: 1px solid black;
        min-width:100px;
        max-width:100px;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
    td:hover i{
        display: block;
        float:right;
        visibility: visible;
    }
    i{
        display: none;
        visibility: hidden;
    }
  </style>

</head>
<body>
<div style="overflow: hidden;width: 400px;">
  <table id="target" class="scroll-example" style="overflow: hidden;">
    <tr>
        <td class="col11">HHHHHHHHHHHHH</td>
        <td class="col2">HHHHHHHHHHH</td>
        <td class="col3">HHHHHHHHHHH</td>
        <td class="col4">HHHHHHHHHHH</td>
        <td class="col5">HHHHHHHHHHH</td>
        <td class="col6">HHHHHHHHHHH</td>
        <td class="col7" width="20px"     style="border-color: white;"></td>
    </tr>
  </table>

  <table id="source" class="scroll-example" style="overflow: scroll;height: 80px;">
    <tr>
        <td class="col1"><i class="fa fa-pencil"></i>AAAAAAAAAAA</td>
        <td class="col2"><i class="fa fa-pencil" aria-hidden="true"></i>AAAAAAAAAAA</td>
        <td class="col1"><i class="fa fa-lock" aria-hidden="true"></i>AAAAAAAAAAA</td>
        <td class="col1"><i class="fa fa-pencil" aria-hidden="true"></i>AAAAAAAAAAA</td>
        <td class="col1"><i class="fa fa-lock" aria-hidden="true"></i>AAAAAAAAAAA</td>
        <td class="col1"><i class="fa fa-lock" aria-hidden="true"></i>AAAAAAAAAAA</td>
    </tr>
    <tr>
        <td class="col1"><i class="fa fa-pencil"></i>AAAAAAAAAAA</td>
        <td class="col2"><i class="fa fa-pencil" aria-hidden="true"></i>AAAAAAAAAAA</td>
        <td class="col1"><i class="fa fa-lock" aria-hidden="true"></i>AAAAAAAAAAA</td>
        <td class="col1"><i class="fa fa-pencil" aria-hidden="true"></i>AAAAAAAAAAA</td>
        <td class="col1"><i class="fa fa-lock" aria-hidden="true"></i>AAAAAAAAAAA</td>
        <td class="col1"><i class="fa fa-lock" aria-hidden="true"></i>AAAAAAAAAAA</td>
    </tr>
    <tr>
        <td class="col1"><i class="fa fa-pencil"></i>AAAAAAAAAAA</td>
        <td class="col2"><i class="fa fa-pencil" aria-hidden="true"></i>AAAAAAAAAAA</td>
        <td class="col1"><i class="fa fa-lock" aria-hidden="true"></i>AAAAAAAAAAA</td>
        <td class="col1"><i class="fa fa-pencil" aria-hidden="true"></i>AAAAAAAAAAA</td>
        <td class="col1"><i class="fa fa-lock" aria-hidden="true"></i>AAAAAAAAAAA</td>
        <td class="col1"><i class="fa fa-lock" aria-hidden="true"></i>AAAAAAAAAAA</td>
    </tr>
    </table>
  </div>
  <script>
  (function() {
    var target = $("#target");
    $("#source").scroll(function() {
      target.prop("scrollTop", this.scrollTop)
            .prop("scrollLeft", this.scrollLeft);
    });
  })();
  </script>
</body>
</html>
0

I managed to make it work with CSS alone.

CSS:

<style type="text/css">
   .scrollable {
      overflow-y: auto; /* make it scrollable if needed */
      height: 20.5em;   /* non-integer height should cut a row in half-ish to visually let the user know it's scrollable in case of a mobile device or no scrollbar */
      display: inline-block;
      overflow-x: hidden;
      resize: vertical; /* optional. In my case, I needed users to be able to vertically resize the table display area */
      border-style: solid;
      border-color: rgba(0, 0, 0, 0.100);
      border-width: 1px; 
      width: 100%;      /* For some reason, the table's container doesn't take up the full column unless this is present */
   }

   .scrollable thead {  /* Stick the header row to the top of the container */
      position: sticky;
      top: 0
   }

   .scrollable tfoot {  /* Stick the footer row to the bottom of the container */
      position: sticky;
      bottom: 0
   }
</style>

For the VisualForce, you'll wrap the pageblocktable with an output panel:

<apex:outputPanel styleClass="scrollable">
    <apex:pageBlockTable value="{! ListItems}" var="i">
        ...
    </apex:pageBlockTable>
</apex:outputPanel>

enter image description here

You must log in to answer this question.

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