I am creating a custom Lightning Component to quickly add products to a quote. The Datatable pulls back all active products, I have a search field that the user can use to filter the products, when I search for Product "ABC", select it, and then search for product "DEF", then select it, I want to be able to add those rows to a new datatable with both products. Currently when I filter the data table it only finds the most recent selected rows.
If I relate it to something I did in my old vb.Net days it would be the "+=" operator, essentially I want to build a list that persists over the users search results.
Here is what I have:
Apex Controller:
public class ProductQuickAddController {
@AuraEnabled
public static List<Product2> getProducts() {
List<Product2> activeProducts = [SELECT Id, Name, ProductCode, Family, Description FROM Product2 where IsActive = True];
//system.debug(activeProducts);
return activeProducts;
}
@AuraEnabled
public static List<Product2> getResults(string searchStr) {
searchStr = '%' +searchStr + '%';
system.debug(searchStr);
List<Product2> activeProducts = [SELECT Id, Name, ProductCode, Family, Description FROM Product2 where (Name like :searchStr or Description like :searchStr) and IsActive = True];
//system.debug(activeProducts);
return activeProducts;
}
}
Component:
<aura:component Controller = "ProductQuickAddController" implements="force:hasRecordId,flexipage:availableForAllPageTypes,force:appHostable,force:lightningQuickAction" access="global">
<!-- attributes -->
<aura:attribute name="productList" type="Object" />
<aura:attribute name="productCols" type="List" />
<aura:attribute name="filteredProducts" type="List" />
<aura:attribute name="selectedRowsCount" type="Integer" default="0"/>
<aura:attribute name="selectedRows" type="List"/>
<aura:attribute name="searchText" type="String" />
<ltng:require styles="{!$Resource.ModalCSS}"/>
<aura:attribute name="addProductsCols" type="List" />
<aura:attribute name="errors" type="Object" default="[]"/>
<aura:attribute name="draftValues" type="Object" default="[]"/>
<!-- handlers-->
<aura:handler name="init" value="{!this}" action="{!c.doInit}" />
<div style="height: 90%; padding: 10px;" aura:id="Products">
<lightning:layout verticalAlign="end">
<lightning:layoutItem flexibility="grow">
<lightning:input label="Search" type="search" value="{!v.searchText}" name="search"/>
</lightning:layoutItem>
<lightning:layoutItem class="slds-p-left_x-small">
<lightning:button variant="brand" label="Search" title="Search" onclick="{!c.filter }" />
</lightning:layoutItem>
</lightning:layout>
<h1>Selected Rows: {!v.selectedRowsCount }</h1>
<center>
<div style="height: 500px; padding: 10px;">
<lightning:datatable
aura:id="tblProducts"
columns="{!v.productCols}"
data="{!v.filteredProducts}"
keyField="Id"
onrowselection="{!c.getSelected}"/>
</div>
</center>
<div id="controls" style="float:right; padding: 10px;">
<lightning:button variant="brand" label="Set Prices" title="Set Prices" onclick="{!c.selectedProducts }" />
</div>
</div>
<div style="height: 500px; overflow: scroll; padding: 10px;" aura:id="addProducts">
<lightning:datatable
aura:id="SelectedProducts"
columns="{!v.addProductsCols}"
data="{!v.selectedRows}"
keyField="Id"
errors="{!v.errors}"
draftValues="{!v.draftValues}"
onsave="{!c.handleSaveEdition}"/>
</div>
</aura:component>
Controller:
({
doInit : function(component, event, helper) {
component.set('v.productCols', [
//{label: 'Id', fieldName: 'Id', type: 'text'},
{label: 'Name', fieldName: 'Name', type: 'text'},
{label: 'Code', fieldName: 'ProductCode', type: 'text'},
{label: 'Family', fieldName: 'Family', type: 'text'},
{label: 'Description', fieldName: 'Description', type: 'text'}
]);
component.set('v.addProductsCols', [
//{label: 'Id', fieldName: 'Id', type: 'text'},
{label: 'Name', fieldName: 'Name', type: 'text'},
{label: 'Description', fieldName: 'Description', type: 'text', editable: true},
{label: 'Sales Price', fieldName: 'Description', type: 'currency', typeAttributes: { currencyCode: 'USD'}, editable: true, typeAttributes: { required: true }},
{label: 'Quantity', fieldName: 'Description', type: 'number', editable: true, typeAttributes: { required: true }}
]);
helper.fetchProducts(component, event);
$A.util.removeClass(component.find("Products"), "slds-hide");
$A.util.addClass(component.find("addProducts"), "slds-hide");
},
filter: function(component, event, helper) {
helper.getSearchResults(component, event);
},
getSelected: function(component, event, helper) {
var prevSelected = component.get("v.selectedRows");
let selectedProds =[];
selectedProds = component.find('tblProducts').getSelectedRows();
component.set("v.selectedRows", selectedProds)
},
selectedProducts: function(component, event, helper) {
$A.util.removeClass(component.find("addProducts"), "slds-hide");
$A.util.addClass(component.find("Products"), "slds-hide");
},
})
Helper:
({
fetchProducts : function(component, event) {
var action = component.get('c.getProducts')
var self = this;
action.setCallback(this, function(response) {
component.set('v.productList', response.getReturnValue());
component.set('v.filteredProducts', response.getReturnValue());
} );
$A.enqueueAction(action);
},
getSearchResults : function(component, event) {
var strSearch = component.get("v.searchText")
var action = component.get('c.getResults')
var self = this;
action.setParams({"searchStr":strSearch});
action.setCallback(this, function(response) {
component.set('v.productList', response.getReturnValue());
component.set('v.filteredProducts', response.getReturnValue());
} );
$A.enqueueAction(action);
}
})
Best Answer
So the fix was adding the following to the Component side:
And in the controller: