0

I've structured a component in a way that either a lightning:datatable aura component or a lightning:dualistbox. The dual list box is used to set the columns attribute of the data table. The issue is that in this way, even if the values of the data table are correct, their width is not: they are shrunk as much as possible. If I resize the window then the columns width will adjust correctly automatically. There is a way to force the data table columns adjustment or to fake the window resizing event?


In the following a minimal example to make my case clearer.

parent.cmp

<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes" access="global">
    <aura:attribute name="data" type="List"/>
    <aura:attribute name="dataTableColumns" type="List"/>
    <lightning:tabset>
        <!-- Table Tab -->
        <lightning:tab label="Table" title="Table">
            <c:datatableChild data="{!v.data}" columns="{!v.dataTableColumns}"/>
        </lightning:tab>

        <!-- Settings Tab -->
        <lightning:tab label="Settings" title="Settings">
            <c:duallistboxChild dataTableColumns="{!v.dataTableColumns}"/>
        </lightning:tab>
    </lightning:tabset>
</aura:component>

datatableChild.cmp

<aura:component >
    <!-- Table Attributes -->
    <aura:attribute name="data" type="Object" access="public" required="true"/>
    <aura:attribute name="columns" type="List" access="public" required="true"/>
    <aura:attribute name="hideCheckBoxColumn" type="Boolean" default="true"/>
    <aura:attribute name="sortedBy" type="String" default="Value1"/>
    <aura:attribute name="sortedDirection" type="String" default="asc"/>
    <aura:attribute name="defaultSortDirection" type="String" default="asc"/>

    <!-- Table -->
    <lightning:datatable
        keyField="Id"
        data="{!v.data}"
        columns="{!v.columns}"
        hideCheckboxColumn="{!v.hideCheckBoxColumn}"
        sortedBy="{!v.sortedBy}"
        sortedDirection="{!v.sortedDirection}"
        defaultSortDirection="{!v.defaultSortDirection}"/>
</aura:component>

duallistboxChild.cmp

<aura:component >
    <!-- Attributes -->
    <aura:attribute 
        name="visibleColumnsOptions" 
        type="List" 
        default="[
            {label: 'Column1', value: 'Value1'},
            {label: 'Column2', value: 'Value2'},
            {label: 'Column3', value: 'Value3'},
            {label: 'Column4', value: 'Value4'},
            {label: 'Column5', value: 'Value5'},
            {label: 'Column6', value: 'Value6'}]" 
        access="public"/>
    <aura:attribute 
        name="visibleColumnsValues" 
        type="List" 
        default="['Value1', 'Value2', 'Value3']"/>
    <aura:attribute 
        name="visibleColumnsRequiredOptions" 
        type="List" 
        default="['Value1']"/>
    <aura:attribute 
        name="dataTableColumns" 
        type="List" 
        access="public"/>

    <!-- Settings -->
    <lightning:dualListbox
        name="visibleColumns"
        label="Select visible columns"
        sourceLabel="Available"
        selectedLabel="Selected"
        options="{!v.visibleColumnsOptions}"
        value="{!v.visibleColumnsValues}"
        onchange="{!c.setDataTableColumns}"/>
</aura:component>

duallistboxChildController.js

({
    setDataTableColumns : function(component, event, helper) {
        const selectedOptions = component.get("v.visibleColumnsValues");
        var columns = [];
        for (let selectedOption of selectedOptions) {
            switch (selectedOption) {
                case 'Value1':
                    columns.push({fieldName: 'Value1', label: 'Column1', sortable: true, type: 'text'});
                    break;
                case 'Value2':
                    columns.push({fieldName: 'Value2', label: 'Column2', sortable: true, type: 'text'});
                    break;
                case 'Value3':
                    columns.push({fieldName: 'Value3', label: 'Column3', sortable: true, type: 'text'});
                    break;
                case 'Value4':
                    columns.push({fieldName: 'Value4', label: 'Column4', sortable: true, type: 'text'});
                    break;
                case 'Value5':
                    columns.push({fieldName: 'Value5', label: 'Column5', sortable: true, type: 'text'});
                    break;
                case 'Value6':
                    columns.push({fieldName: 'Value6', label: 'Column6', sortable: true, type: 'text'});
                    break;
                default:
                    console.error("An unexpected column has been selected. Selected column: " + selectedOption);
                    // Do something, this case should never happen
                    break;
            }
        }
        component.set('v.dataTableColumns', columns);
    }
})

The real page is much more complex. However, for the sake of simplicity in the following there are a couple of screenshot of the situation with the above code.

By simply open the parent and set whatever value of columns in the setting tab this is what happens when the switch back to the table tab:

actual

After taking the step above, resize the window and this is what happens:

expected

What I want is the effect of the second screenshot without having to manually resize the window.

I tried to pass the initial width of the columns inside the columns attribute of lightning:dataTable and it works. I mean that the column width (expressed as pixels) is the same I've provided. However this doesn't solve my troubles since the width is no longer reactive. I tried with percentage values but it broken the column layout.

11
  • 1
    Please share code which you have tried. Commented May 30, 2019 at 10:38
  • @DhanikLalSahni Done.
    – gvgramazio
    Commented May 30, 2019 at 11:13
  • try with initialWidth attribute in column object like {label: 'Column1', value: 'Value1',initialWidth: 34} if still not fix please post image
    – sdandamud1
    Commented May 30, 2019 at 12:58
  • @sdandamud1It works. However how should I've been able to set the correct value for the columns?
    – gvgramazio
    Commented May 30, 2019 at 13:07
  • @sdandamud1I tried width percentage values but percentages broke the layout.
    – gvgramazio
    Commented May 30, 2019 at 13:14

2 Answers 2

1

I think there's an easier way. I just added a listener in the init of my component that forces the datatable to redraw, like so:

    // This catches the 'resize' event, which is whenever the browser window resizes.
    window.addEventListener( 'resize', function(){
        // Hide/Show the datatable to get it to resize
        component.set( "v.renderDataTable","false" );
        component.set( "v.renderDataTable","true" );
    });

..and then in the component, I do this:

<aura:attribute name="renderDataTable" type="Boolean" default="true"/>
        <aura:renderIf isTrue="{!v.renderDataTable}">
            <lightning:datatable        suppressBottomBar="true"      
                                        aura:id="table2"    
                                        columns="{! v.columns }"
                                        data="{! v.opendata }"
                                        keyField="Id"
                                        selectedRows="{! v.selectedRows }"
                                        onsort="{!c.updateSortingOpen}"
                                        sortedBy="{!v.sortedByOpen}"
                                        sortedDirection="{!v.sortedDirectionOpen}"
                                        oncellchange="{! c.handleSaveEdition2 }" 
                                        onrowselection="{! c.updateSelected }"
                                        onrowaction="{! c.handleRowAction2 }" 
                                        draftValues="{! v.draftValues }"
                                        hideCheckboxColumn="true"/>
        </aura:renderIf>

Seems to work.

0

I was able to solve it. I don't like this solution but I didn't find a better way. Basically, I'm forcing the render of the table when its parent tab is active.

The solution is to embrace the datatableChild component in an aura:renderIf. The helper variable can have any name and it is set to true when the Table tab is active and it set to false when the other tab is active. To achieve this the onactive attribute of lightning:tab can be used.

parent.cmp

<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes" access="global">
    <aura:attribute name="data" type="List"/>
    <aura:attribute name="dataTableColumns" type="List"/>
    <aura:attribute name="flag" type="Boolean"/>

    <lightning:tabset>
        <!-- Table Tab -->
        <lightning:tab label="Table" title="Table" onactive="{!c.setFlag}">
            <aura:renderIf isTrue="{!v.flag}">
                <c:datatableChild data="{!v.data}" columns="{!v.dataTableColumns}"/>
            </aura:renderIf>
        </lightning:tab>

        <!-- Settings Tab -->
        <lightning:tab label="Settings" title="Settings" onactive="{!c.unsetFlag}">
            <c:duallistboxChild dataTableColumns="{!v.dataTableColumns}"/>
        </lightning:tab>
    </lightning:tabset>
</aura:component>

parentController.cmp

({
    setFlag : function(component, event, helper) {
        component.set("v.flag", true);
    },

    unsetFlag : function(component, event, helper) {
        component.set("v.flag", false);
    }
})

I discourage the alternative of using aura:if instead of aura:renderIf. It completely reinitialise the component while I'm interested in render only.

As I said, I don't like it very much but it's the best I've achieved so far.

2
  • P.S. aura:renderIf is deprecated. Use aura:if instead.
    – sfdcfox
    Commented May 30, 2019 at 16:47
  • @sfdcfox they have a different behaviour. aura:if reinitialise the component and I don’t want it.
    – gvgramazio
    Commented May 30, 2019 at 16:49

You must log in to answer this question.

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