7

There are use cases, such as the expense tracker app in the Lightning Components Developer's Guide, where users are entering data into a dynamic list that grows with each user input submission. My question is, in these situations, what is the most efficient way to implement a UI element that allows the user to remove an item from the list?

enter image description here

2 Answers 2

8

Luckily the aura:iteration component has a super convenient, built-in attribute called indexVar. By leveraging indexVar I am able to pass the array index to the controller action, which can then use Array.prototype.splice() to remove an element from the list.

For example, consider the following aura:iteration element:

<aura:iteration items="{!v.leads}" var="lead" indexVar="i">
    <tr>
        <td>
            <ui:button label="Remove" press="{!c.handleRemoveLeadButtonClick}">
                <span data-index="{!i}"></span>
            </ui:button>
            <a href="#" data-index="{!i}" onclick="{!c.handleRemoveLeadAnchorClick}">
                Remove
            </a>
        </td>
        <td>{!lead.FirstName}</td>
        <td>{!lead.LastName}</td>
        <td>{!lead.Company}</td>
        <td>{!lead.Email}</td>
    </tr>
</aura:iteration>

I've intentionally included a ui:button and a standard HTML a (anchor) to show how to get the index value in both cases. The controller actions are shown below.

({
    handleRemoveLeadButtonClick : function(component, event, helper) {
        var self = this;  // safe reference

        var domEvent = event.getParams().domEvent;
        var bodySpan = domEvent.target.nextSibling;
        var index = bodySpan.dataset.index;
        helper.removeLead(component, index);
    },
    handleRemoveLeadAnchorClick : function(component, event, helper) {
        var self = this;  // safe reference

        var index = event.target.dataset.index;
        helper.removeLead(component, index);
    }
)}

And helper.removeLead() is defined as follows:

({
    removeLead : function(component, index) {
        var leads = component.get("v.leads");
        leads.splice(index, 1);
        component.set("v.leads", leads);
    }
})
1
  • What if I'm using a checkbox to remove an item? I'm neither using an anchor nor a button in my code.
    – Tyler Zika
    Commented Aug 4, 2016 at 1:26
1

I added a button in expenseList.cmp to handle removing of the expense item.

<ui:button label="Remove" press="{!c.remove}"/>

Then, I created an event, deleteExpenseItem.evt, to capture and pass the removed item.

<aura:event type="APPLICATION">
 <aura:attribute name="expense" type="Expense__c"/>
</aura:event>

Fire the event in expenseListController.js.

remove: function(component, evt, helper) {
    var expense = component.get("v.expense");    
    var deleteEvent = $A.get("e.c:deleteExpenseItem");
    deleteEvent.setParams({ "expense": expense }).fire();
}

Handle the event in form.cmp.

<aura:handler event="c:deleteExpenseItem" action="{!c.deleteEvent}" />

Add the handler to formController.js.

deleteEvent : function(component, event, helper) {
    helper.deleteExpense(component, event.getParam("expense"));
}

Call your Apex controller to delete the expense item and update the view in formHelper.js.

deleteExpense : function(component, expense, callback) {

    var action = component.get("c.deleteExpense");
    var self = this;
    action.setParams({
        "expense": expense
    });
    action.setCallback(this, function(response) {
        var state = response.getState();
        if (state === "SUCCESS") {
            //remove only the deleted expense from view
            var expenses = component.get("v.expenses");
            var items = [];
            for (i = 0; i < expenses.length; i++) {
                if(expenses[i]!==expense) {
                    items.push(expenses[i]);  
                }
            }
            component.set("v.expenses", items);
            self.updateTotal(component);
        }
    });
    $A.enqueueAction(action);
}

And don't forget to include the delete DML operation in ExpenseController.apxc.

@AuraEnabled
public static Expense__c deleteExpense(Expense__c expense) {
    delete expense;
    return expense;
}
1
  • This is incredible for such a simple operation. The effect is the same as if you accessed the element and called a .remove on it. Why wouldn't there be a .remove? I can dynamically create and add components why can't I also remove them in a very simple manner especially if I have a reference to the component I created dynamically in the first place. This is insane complexity for things that are so simple. Commented Sep 29, 2016 at 16:24

You must log in to answer this question.

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