1

I have a data table based on Lightning component. In one of the column it displays Icon and when user click it should expand and show more information as child row. Is it possible to achieve this without using JQuery?

<table aura:id="companyList" class="slds-table slds-table--bordered slds-table_cell-buffer slds-max-medium-table--stacked-horizontal slds-hide" role="listbox">
    <thead>
    <tr >
        <th colspan="4" scope="col">
            <aura:if isTrue="{!v.searching}">
                <div role="status" class="slds-spinner slds-spinner_large slds-spinner_brand ">
                    <span class="slds-assistive-text">Searching for Companies</span>
                    <div class="slds-spinner__dot-a"></div>
                    <div class="slds-spinner__dot-b"></div>
                </div>
            </aura:if>
            <div class="slds-grid">
                <div class="slds-col slds-align-bottom">
                    <p class="slds-text-body--small page-header__info">{!v.SECompanies.length} Record(s)</p>
                </div>
            </div>
        </th>
    </tr>
    <tr class="slds-text-heading--label">
        <th scope="row" class="nobordertop">Action</th>
        <th scope="col" class="nobordertop">Protection Info</th>
        <th scope="col" class="nobordertop">Company ID</th>
        <th scope="col" class="nobordertop">Company</th>
        <th scope="col" class="nobordertop">Ultimate Parent Co</th>
        <th scope="col" class="nobordertop">Street</th>
        <th scope="col" class="nobordertop">Address</th>
    </tr>
    </thead>
    <tbody>
    <aura:iteration items="{!v.SECompanies}" var="company" indexVar="rowIndex">
        <tr data-data="{!rowIndex}">
            <td data-data="{!rowIndex}">
                <lightning:buttonMenu onselect="{!c.handleSelect}" alternativeText="Toggle menu">
                    <lightning:menuItem label="Edit" value="menuitem1" iconName="action:edit" />
                    <lightning:menuItem label="New Opportunity" value="menuitem2" iconName="action:new_opportunity" />
                </lightning:buttonMenu>
            </td>
            <td data-index="{!rowIndex}" data-label="Protection Info" title="Protection Info">
                <button class="slds-button slds-button--icon-border-filled slds-button--icon-border-small" onclick="{!c.handleIconClick}">
                    <lightning:icon class="icon" iconName="{!company.protectionImageSource}" variant="warning" size="small" title="Click to view protection information"/>
                </button>
            </td>
            <td data-label="Company ID" title="Company ID">
                <div><a data-record="{!company.companyId}" >{!company.companyId}</a></div>
            </td>
            <td data-label="Company Name" title="Company Name">
                <button class="slds-button slds-button-neutral" onclick="{!c.companySelected}" data="{!company}" role="option">{!company.companyName}</button>
            </td>
            <td data-label="Ultimate Parent Name" title="Ultimate Parent Name">
                <div><a data-record="{!company.ultimateParentName}" >{!company.ultimateParentName}</a></div>
            </td>
            <td data-label="Street" title="Street">
                <div><a data-record="{!company.street1}" >{!company.street1}</a></div>
            </td>
            <td data-label="Address" title="Address">
                <div><a data-record="{!company.address}" >{!company.address}</a></div>
            </td>
        </tr>
    </aura:iteration>
    </tbody>
</table>



({
doInit : function(component, event, helper) {
    component.set("v.rows", [
        { Name: "Action",
          expanded: false
        },
        { Name: "Protection Info",
          expanded: false,
        children: [
        { Name: "Protection Desc" }
        ]},
        { Name: "Company ID",
          expanded: false
        },
        { Name: "Company",
          expanded: false
        },
        {
          Name: "Ultimate Parent Co",
          expanded: false
        },
        {
          Name: "Street",
          expanded: false
        },
        {
          Name: "Address",
          expanded: false
        }
    ]);     
}

});

handleIconClick: function(component, event) { var rows = component.get("v.rows"); rows[event.target.dataset.index].expanded = !rows[event.target.dataset.index].expanded; component.set("v.rows", rows); }

enter image description here

1 Answer 1

10

Is it possible to achieve this without using JQuery?

Yes. If you can do something with JQuery, you can do it without JQuery. It's all JavaScript. As an addendum, anything you can do in JQuery you can do without JQuery and get better performance.

In the interest of keeping things brief, I'm not going to write out a full copy of your code with modifications, but a smaller, more generalized example that demonstrates how to do what you're trying to do.


<aura:application >
    <aura:attribute name="rows" type="Object[]" />
    <aura:handler name="init" value="{!this}" action="{!c.init}" />

    <table>
        <tbody>
            <aura:iteration items="{!v.rows}" var="row" indexVar="rowIndex">
                <tr>
                    <td data-index="{!rowIndex}" onclick="{!c.toggle}">
                        {!row.Name}
                    </td>
                </tr>
                <aura:if isTrue="{!row.expanded}">
                    <aura:iteration items="{!row.children}" var="child">
                        <tr>
                            {!child.Name}
                        </tr>
                    </aura:iteration>
                </aura:if>
            </aura:iteration>
        </tbody>
    </table>
</aura:application>

({
    init: function(cmp, evt) {
        cmp.set("v.rows", [
            {Name: "A",
            expanded: false,
            children: [
            { Name: "A1" },
            { Name: "A2" }
            ]},
            {Name: "B",
            expanded: false,
            children: [
            { Name: "B1" },
            { Name: "B2" }
            ]},
            {Name: "C",
            expanded: false,
            children: [
            { Name: "C1" },
            { Name: "C2" }
            ]}
                ]);
    },
    toggle: function(cmp, evt) {
        var rows = cmp.get("v.rows");
        rows[evt.target.dataset.index].expanded = !rows[evt.target.dataset.index].expanded;
        cmp.set("v.rows", rows);
    }
})

As you can see from this code, it's a trivial matter to simply render the extra rows when the "expanded" attribute has been toggled. You should be able to modify this example to suit your needs.

I've purposefully left out all styling and fluff to get to the heart of the matter, which I think this app demonstrates easily. Most likely, you'll just need to add an "expanded" attribute to your data's information, and then toggle it as appropriate.

There's lots of other things you could do with this as well, such as querying the database, making a callout, or whatever else it is you want/need to do to get the data.

3
  • @user28452 did you add data-index="{!rowIndex}" to your button? event.target will be the button...
    – sfdcfox
    Jul 27, 2017 at 6:45
  • Apologies on getting late to this. In my situation I have data from the rest call. <aura:attribute name="SECompanies" type="KF_RESTAPI.Company[]"/> And what you suggested is <aura:attribute name="rows" type="Object[]" /> And your code sample iterating over the object that got initialized. <aura:iteration items="{!v.rows}" var="row" indexVar="rowIndex"> And I am wondering how would I do that with below ? <aura:iteration items="{!v.SECompanies}" var="company" indexVar="rowIndex">
    – user28452
    Oct 19, 2017 at 5:19
  • @user28452 Yes, my code was just generic code. The code you wrote should be correct.
    – sfdcfox
    Oct 19, 2017 at 7:51

You must log in to answer this question.

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