Deep Dive into Lightning Design System(Table Column resizing)

IntroDUCTION

In this series, I will share the practical example along with some reusable component for building the custom lightning component using SLDS. Salesforce Lightning Design System(SLDS) is the custom stylesheet used in lightning experience by Salesforce.

PROBLEM STATEMENT

As we all have used tables in some point of our career, sometimes there are so many columns, we have to truncate the data to adjust according to column width. Client usually prefer to have column resizing option for end users to adjust the column width as per their ease. We will implement the column resizing functionality in custom Lightning component.

PROPOSED SOLUTION

First we will use the dummy table shared by the Lightning Design System for Column Resizing. I have truncated some columns for better visibility.

We need to store the Original width of the selected column to calculate the new width for which I have defined the oldWidth attribute to store the value. We also need the distance of the selected column width from the left of the screen to identify the start point from where user start to drag the column. We have used mouseStart attribute for the same.

We have used two mouse events to identify when user start to drag and when user is dragging the column for adjusting the width.  onmousedown will be fired when user click on the column divider element and ondrag will be fired when user is dragging the column divider element.

The Component Markup will be:

<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId" access="global" >
    <aura:attribute name="mouseStart" type="string" />
    <aura:attribute name="oldWidth" type="string" />
    <table class="slds-table slds-table--bordered slds-table--fixed-layout slds-box slds-max-medium-table--stacked-horizontal" role="grid">
        <thead>
            <tr class="slds-line-height--reset">
                <th class="slds-is-resizable slds-text-title--caps" scope="col">
                    <span class="slds-truncate" title="Name">Name</span>
                    <div class="slds-resizable">
                        <input type="range" min="20" max="1000" class="slds-resizable__input slds-assistive-text" id="cell-resize-handle-602" tabindex="0" />
                        <span class="slds-resizable__handle" onmousedown="{!c.calculateWidth}" ondrag="{!c.setNewWidth}">
                            <span class="slds-resizable__divider"></span>
                        </span>
                    </div>
                </th>
                <th class="slds-is-sortable slds-is-resizable slds-text-title--caps" scope="col">
                    <span class="slds-truncate" title="Account Name">Account Name</span>
                    <div class="slds-resizable">
                        <input type="range" min="20" max="1000" class="slds-resizable__input slds-assistive-text" id="cell-resize-handle-603" tabindex="0" />
                        <span class="slds-resizable__handle" onmousedown="{!c.calculateWidth}" ondrag="{!c.setNewWidth}">
                            <span class="slds-resizable__divider"></span>
                        </span>
                    </div>
                </th>
                <th class="slds-is-sortable slds-is-resizable slds-text-title--caps" scope="col">
                    <span class="slds-truncate" title="Close Date">Close Date</span>
                    <div class="slds-resizable">
                        <input type="range" min="20" max="1000" class="slds-resizable__input slds-assistive-text" id="cell-resize-handle-604" tabindex="0" />
                        <span class="slds-resizable__handle" onmousedown="{!c.calculateWidth}" ondrag="{!c.setNewWidth}">
                            <span class="slds-resizable__divider"></span>
                        </span>
                    </div>
                </th>
                <th class="slds-is-sortable slds-is-resizable slds-text-title--caps" scope="col">
                    <span class="slds-truncate" title="Stage">Stage</span>
                    <div class="slds-resizable">
                        <input type="range" min="20" max="1000" class="slds-resizable__input slds-assistive-text" id="cell-resize-handle-605" tabindex="0" />
                        <span class="slds-resizable__handle" onmousedown="{!c.calculateWidth}" ondrag="{!c.setNewWidth}">
                            <span class="slds-resizable__divider"></span>
                        </span>
                    </div>
                </th>
                <th class="slds-is-sortable slds-is-resizable slds-text-title--caps" scope="col">
                    <span class="slds-truncate" title="Confidence">Confidence</span>
                    <div class="slds-resizable">
                        <input type="range" min="20" max="1000" class="slds-resizable__input slds-assistive-text" id="cell-resize-handle-606" tabindex="0" />
                        <span class="slds-resizable__handle" onmousedown="{!c.calculateWidth}" ondrag="{!c.setNewWidth}">
                            <span class="slds-resizable__divider"></span>
                        </span>
                    </div>
                </th>
            </tr>
        </thead>
        <tbody>
            <tr class="slds-hint-parent">
                <th scope="row">
                    <div class="slds-truncate" title="Acme - 1,200 Widgets"><a href="javascript:void(0);">Acme - 1,200 Widgets</a></div>
                </th>
                <td role="gridcell">
                    <div class="slds-truncate" title="Acme">Acme</div>
                </td>
                <td role="gridcell">
                    <div class="slds-truncate" title="4/10/15">4/10/15</div>
                </td>
                <td role="gridcell">
                    <div class="slds-truncate" title="Value Proposition">Value Proposition</div>
                </td>
                <td role="gridcell">
                    <div class="slds-truncate" title="30%">30%</div>
                </td>
            </tr>
            <tr class="slds-hint-parent">
                <th scope="row">
                    <div class="slds-truncate" title="Acme - 200 Widgets"><a href="javascript:void(0);">Acme - 200 Widgets</a></div>
                </th>
                <td role="gridcell">
                    <div class="slds-truncate" title="Acme">Acme</div>
                </td>
                <td role="gridcell">
                    <div class="slds-truncate" title="1/31/15">1/31/15</div>
                </td>
                <td role="gridcell">
                    <div class="slds-truncate" title="Prospecting">Prospecting</div>
                </td>
                <td role="gridcell">
                    <div class="slds-truncate" title="60%">60%</div>
                </td>
            </tr>
            <tr class="slds-hint-parent">
                <th scope="row">
                    <div class="slds-truncate" title="salesforce.com - 1,000 Widgets"><a href="javascript:void(0);">salesforce.com - 1,000 Widgets</a></div>
                </th>
                <td role="gridcell">
                    <div class="slds-truncate" title="salesforce.com">salesforce.com</div>
                </td>
                <td role="gridcell">
                    <div class="slds-truncate" title="1/31/15 3:45PM">1/31/15 3:45PM</div>
                </td>
                <td role="gridcell">
                    <div class="slds-truncate" title="Id. Decision Makers">Id. Decision Makers</div>
                </td>
                <td role="gridcell">
                    <div class="slds-truncate" title="70%">70%</div>
                </td>
            </tr>
        </tbody>
    </table>
</aura:component>

 

We have defined calculateWidth method which will be called when onmousedown event will be fired. It will calculate the existing width of the selected column and it’s distance from left of the screen which will be stored in custom attributes defined by us. The other method setNewWidth will be called when user is dragging(ondrag event) the column divider to calculate and set the new width of the column.

The Component Controller will be:

  ({
	calculateWidth : function(component, event, helper) {
			var childObj = event.target
            var parObj = childObj.parentNode;
            var count = 1;
            //parent element traversing to get the TH
            while(parObj.tagName != 'TH') {
                parObj = parObj.parentNode;
                count++;
            }
        	console.log('final tag Name'+parObj.tagName);
        	//to get the position from the left for storing the position from where user started to drag
        	var mouseStart=event.clientX; 
        	component.set("v.mouseStart",mouseStart);
        	component.set("v.oldWidth",parObj.offsetWidth);
	},
    
    setNewWidth : function(component, event, helper) {
			var childObj = event.target
            var parObj = childObj.parentNode;
            var count = 1;
      		//parent element traversing to get the TH
            while(parObj.tagName != 'TH') {
                parObj = parObj.parentNode;
                count++;
            }
        	var mouseStart = component.get("v.mouseStart");
        	var oldWidth = component.get("v.oldWidth");
        	//To calculate the new width of the column
        	var newWidth = event.clientX- parseFloat(mouseStart)+parseFloat(oldWidth);
        	parObj.style.width = newWidth+'px';//assign new width to column
    }
})

The final look of the lightning component will be:

Lightning Table Column Resizing