Skip to main content

How to Build Dynamic Drag-and-Drop Tables in Salesforce Visualforce Using DataTables & SLDS

Standard Salesforce list views and standard components can often feel rigid. When business users want to reorder columns on the fly or hide unnecessary fields to focus on specific data, standard Visualforce tables fall short. To solve this, developers can combine the robust data-handling of the jQuery DataTables plugin with the modern look of the Salesforce Lightning Design System (SLDS).

In plain words: You can add highly interactive capabilities to standard Salesforce tables—such as drag-and-drop column reordering, quick search, and toggleable column visibility—by injecting the jQuery DataTables library into your Visualforce pages and styling it with SLDS.

Key Points Summary

  • The <apex:slds /> tag seamlessly applies the modern Lightning aesthetic to legacy Visualforce pages.
  • Using the ColReorder extension allows users to drag and drop column headers to rearrange table layouts in real-time.
  • Using the ColVis extension generates a dynamic dropdown menu, letting users show or hide specific columns instantly.
  • While this pattern is highly effective for Visualforce tech debt, modern orgs should consider migrating these features to Lightning Web Components (LWC).
Dynamic List View UI with Column Reordering in Salesforce

Required Libraries & Assets

To make this work, you need to import specific JavaScript and CSS files. For production environments, it is highly recommended to upload these as Static Resources rather than linking to external CDNs for security and performance.

  • SLDS: Native Salesforce styling via <apex:slds />.
  • jQuery & DataTables Core: The engine handling DOM manipulation, pagination, and sorting.
  • Buttons & ColVis Extension: Adds the "Change Columns" button to toggle visibility.
  • ColReorder Extension: Enables the native drag-and-drop feature on the table headers.

Complete Code Walkthrough (Visualforce)

Below is a clean, self-contained Visualforce page markup that integrates DataTables with custom SLDS CSS overrides to make the table look perfectly native to Lightning Experience.

<apex:page showHeader="false" docType="html-5.0" sidebar="false" lightningStylesheets="true">
    <html xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" lang="en">
        <head>
            <!-- Import Salesforce Lightning Design System (SLDS) -->
            <apex:slds /> 
            
            <!-- DataTables & Extensions CSS (Use Static Resources in Production) -->
            <link rel="stylesheet" href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css"/>
            <link rel="stylesheet" href="https://cdn.datatables.net/buttons/1.5.6/css/buttons.dataTables.min.css"/>
            <link rel="stylesheet" href="https://cdn.datatables.net/colreorder/1.5.1/css/colReorder.dataTables.min.css"/>

            <style>                
                /* Custom SLDS Overrides to blend DataTables seamlessly */
                #data th {
                    background-color: #539fc6 !important;
                    color: white;
                    vertical-align: middle;
                    white-space: nowrap;
                }
                .slds-scope .slds-icon-text-default {
                    fill: rgb(255, 255, 255) !important;
                }
                button.dt-button.active, .buttons-colvis {
                    background: #539fc6 !important;
                    color: white !important;
                    font-weight: bold !important;
                }
                .dt-button-collection {
                    position: fixed !important;
                    margin-top: -175px !important;
                    max-height: 500px !important;
                    overflow-y: auto !important;
                }
            </style>
        </head>        
        
        <body>
            <apex:form>
                <!-- Main SLDS Wrapper -->
                <div class="slds-scope slds-p-around_medium" style="background-color: white; min-height: 100vh;"> 
                    
                    <!-- Header Section -->
                    <div class="slds-grid slds-grid_vertical-align-center slds-m-bottom_medium">
                        <div class="slds-col">
                            <h1 class="slds-text-heading_medium">
                                <!-- Standard SLDS SVG Icon -->
                                <span class="slds-icon_container slds-icon-standard-account slds-m-right_small">
                                    <svg class="slds-icon slds-icon_small" aria-hidden="true">
                                        <use xlink:href="/apexpages/slds/latest/assets/icons/standard-sprite/svg/symbols.svg#account"></use>
                                    </svg>
                                </span>
                                Dynamic Record List
                            </h1>
                        </div>
                    </div>

                    <!-- Data Table Container -->
                    <div style="width:100%; overflow-x: auto;">
                        <apex:outputPanel id="RequestTable">
                            <table id="data" class="slds-table slds-table_cell-buffer slds-table_bordered slds-table_striped" style="width:100%;">
                                <thead>         
                                    <tr>
                                        <th>Account Name</th>
                                        <th>Industry</th>
                                        <th>Phone</th>
                                        <th>Annual Revenue</th>
                                    </tr>
                                </thead>
                                <tbody>
                                    <tr>
                                        <td>Acme Corp</td>
                                        <td>Manufacturing</td>
                                        <td>(555) 123-4567</td>
                                        <td>$500,000</td>
                                    </tr>
                                    <tr>
                                        <td>Stark Industries</td>
                                        <td>Technology</td>
                                        <td>(555) 987-6543</td>
                                        <td>$2,000,000</td>
                                    </tr>
                                </tbody>
                            </table>
                        </apex:outputPanel>
                    </div>
                </div>
            </apex:form>

            <!-- Required JavaScript Libraries (Use Static Resources in Production) -->
            <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
            <script src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
            <script src="https://cdn.datatables.net/buttons/1.5.6/js/dataTables.buttons.min.js"></script>
            <script src="https://cdn.datatables.net/buttons/1.5.6/js/buttons.colVis.min.js"></script>
            <script src="https://cdn.datatables.net/colreorder/1.5.1/js/dataTables.colReorder.min.js"></script>

            <!-- DataTables Initialization -->
            <script>
                $(document).ready(function() {
                    $('#data').DataTable({
                        dom: 'Bfrtip',
                        colReorder: true, // Enables Drag and Drop column reordering
                        buttons: [
                            {
                                extend: 'colvis', // Enables Show/Hide column visibility menu
                                text: 'Change Columns'
                            }
                        ]
                    });
                });
            </script>
        </body>
    </html>
</apex:page>
Step-by-Step Implementation Guide:
  1. Create a new Visualforce Page in your Salesforce org and set lightningStylesheets="true" to modernize default inputs.
  2. Upload the jQuery and DataTables libraries as Static Resources (highly recommended to avoid CORS and CDN blockages).
  3. Wrap your core HTML table inside a <div class="slds-scope"> container so standard SLDS classes apply cleanly without affecting the Salesforce header.
  4. Initialize the table via JavaScript, passing colReorder: true to enable drag-and-drop and registering the colvis button array.

Common Developer Pitfalls

Developer Trap: The AJAX Rerendering Bug
If your Visualforce page uses an <apex:actionFunction> or a reRender attribute on the table container (e.g., refreshing data via a command button), DataTables will lose its DOM state and disappear or freeze. Solution: Always destroy and re-initialize the DataTable instance inside an oncomplete callback whenever you re-render the surrounding panel!

Frequently Asked Questions (FAQ)

Q: Can I use jQuery DataTables inside a Lightning Web Component (LWC)?

A: Yes, you can load third-party scripts in LWC using the lightning/platformResourceLoader (loadScript and loadStyle methods). However, you must be cautious of Lightning Web Security (LWS) strict DOM access rules. The script must only interact with the DOM elements inside your component's template.

Q: Does the standard `lightning-datatable` support drag-and-drop column reordering?

A: As of the latest Salesforce releases, the standard lightning-datatable supports text wrapping, inline editing, and column resizing, but it does not natively support drag-and-drop column reordering. This is why external libraries or highly customized LWC solutions are still relevant for specific UX requirements.

Q: How do I handle large datasets over 10,000 records?

A: If you load thousands of records directly onto the page, the browser will crash. You should implement Server-Side Processing in DataTables, where the plugin fires an AJAX request to an @RemoteAction Apex method to query records using SOQL LIMIT and OFFSET dynamically as the user paginates.

Core Rule: Use the ColReorder extension for position shifts, the ColVis extension for dynamic visibility, and wrap everything in SLDS for a seamless UI match.
360 Summary Card
  • UI Framework: Salesforce Lightning Design System (SLDS) via <apex:slds />
  • Core Logic Engine: jQuery DataTables
  • Key Extensions: ColReorder (Drag & Drop) & ColVis (Hide/Show)
  • Modern Consideration: Use LWC lightning-datatable where possible, falling back to loaded third-party scripts only when advanced UX (like drag-and-drop) is strictly required.