[SalesForce] Lightning: with dynamic column count, want fixed width columns and scrolling instead of automatic resizing

thanks as always, you dudes are the wind beneath my wings.

What I have: A <table> that initializes with 2 columns, and a button that adds an additional column with each click (table is built using <aura:iteration>). The table takes up the entire width of its parent <lightning:Card> container, and the initial columns take up the width of the table. As new columns are added, all columns auto-resize to equal widths so they always take up the width of the table.

Example:
2 columns ('header' column and initial added column)
Several columns take up the same width as just 2

What I want: Instead of columns dynamically resizing themselves, I'd like each column to be a fixed width, filling up the table width as added, with a horizontal scroll bar appearing once the columns exceed the table width

Code:

You can see my failed attempt at using <ui:scrollerWrapper> and slds-scrollable_x. At one point I added a style="width:250px" to the <th> elements in the table body – this set the column widths fixed until they filled the table – then they started resizing again.

<ui:scrollerWrapper>
            <div class="slds-scrollable_x">
                <table class="slds-table slds-table_cell-buffer slds-table_bordered">
                    <thead>
                        <tr class="slds-line-height_reset">
                            <th class="slds-text-title_caps" scope="col">
                                <div class="slds-truncate" title="Entity Name">Entity</div>
                            </th>
                            <aura:iteration items="{!v.tablePeriods}" var="period" indexVar="colNum"> 
                                <th class="slds-text-title_caps" scope="col">
                                    <lightning:input aura:id ="periodLabel" placeholder="Enter Period Label..." value="{!period.label}"/>
                                </th>
                            </aura:iteration>
                        </tr>
                    </thead>
                    <tbody>
                        <aura:iteration items="{!v.tableRows}" var="row" indexVar="rowNum">
                            <tr class="slds-hint-parent">
                                <th data-label="Entity Name" scope="row">
                                    <div class="slds-truncate">
                                        {!row.entityName}
                                    </div>
                                </th>
                                <aura:iteration items="{!v.tablePeriods}" var="p" indexVar="colNum">
                                    <th>
                                        <lightning:select aura:id="selectList">
                                            <option value="">choose one...</option>                                      
                                            <aura:iteration items="{!row.options}" var="option">               
                                                <option value="{!option.label}" selected="{!option.selected}" >{!option.label}</option>                                                                                        
                                            </aura:iteration>
                                        </lightning:select>
                                    </th>
                                </aura:iteration>
                            </tr>
                        </aura:iteration>
                    </tbody>
                </table>
            </div>
        </ui:scrollerWrapper>

Best Answer

Table elements always expand to take up all available space. Instead, you'll want to use normal div elements. I'm not going to try and build a perfectly working example, but you'll want to start off like this:

<div class="slds-scrollable_x">
  <div ...> <!-- set table styles here -->
    <lightning:layout>
      <aura:iteration ...>
        <lightning:layoutItem size="4">
          ...
        </lightning:layoutItem>
     </aura:iteration>
   </div>
   <aura:iteration ...>
     <lightning:layout>
       <aura:iteration ...>
         <lightning:layoutItem size="4">
           ...
         </lightning:layoutItem>
       </aura:iteration>
     </lightning:layout>
   </aura:iteration>
 </div>
</div>

This will produce the effect you're looking for without the use of a table element.


Edit: Here's a really simple example app that demonstrates the logic I'm describing.

<aura:application extends="force:slds">
    <aura:attribute name="columns" type="Integer" default="1" />
    <aura:attribute name="rows" type="List" default="[['Column 1']]" />
    <lightning:slider label="Columns" step="1" value="{!v.columns}" onchange="{! c.handleChange }"/>

    <div class="slds-scrollable_x">
        <aura:iteration items="{!v.rows}" var="row">
            <lightning:layout>
                <aura:iteration items="{!row}" var="col">
                    <lightning:layoutItem size="2">
                        {!col}
                    </lightning:layoutItem>
                </aura:iteration>
            </lightning:layout>
        </aura:iteration>
    </div>
</aura:application>

({
    handleChange: function(component, event, helper) {
        var data = [];
        var cols = component.get("v.columns");
        var row = [];
        while(row.length < cols) {
            row.push("Column "+(row.length+1));
        }
        while(data.length < 10) {
            data.push(row);
        }
        component.set("v.rows", data);
    }
})
Related Topic