I have created a custom Aura component to add quote lines in a Quote. We have a custom Product in our system. When someone selects that product, they get options for how many times they want to add that product to the Quote. Based on the number they select, in the next screen, I am displaying the same selected products multiple times with options to edit some fields like Unit Price, Product Name, and some more fields.
We also have a custom sort order where they enter the value in which order they want to add products. When I click on sort, I lose the adjusted list price value, whereas other values remain as they are. This works fine when I add only two products, but as soon as I add a third product, this value gets reset to the default value for some rows.
first Screen HTML:
<aura:attribute name="selectedCustomProducts" type="Object"/>
<aura:if isTrue="{!v.displayCustomProduct}">
<!-- Modal/Popup Box starts here-->
<section role="dialog" tabindex="-1" aria-labelledby="modal-heading-01" aria-modal="true" aria-describedby="modal-content-id-1" class="slds-modal slds-fade-in-open">
<div class="slds-modal__container">
<!-- Modal/Popup Box Header Starts here-->
<header class="slds-modal__header">
<lightning:buttonIcon iconName="utility:close"
onclick="{! c.closeModel }"
alternativeText="close"
variant="bare-inverse"
class="slds-modal__close"/>
<h2 id="modal-heading-01" class="slds-text-heading_medium slds-hyphenate slds-align_absolute-center">Custom Product Input</h2>
</header>
<!--Modal/Popup Box Body Starts here-->
<div class="slds-modal__content slds-p-around_medium" id="modal-content-id-1">
<lightning:card title="">
<table class="slds-table slds-table--bordered ">
<thead>
<tr class="slds-text-title--caps">
<th scope="col" class="slds-size_4-of-12">
<div style="margin-left:0 rem;" class="slds-truncate" required="true" title="Product">Product Name</div>
</th>
<th scope="col" class="slds-size_6-of-12">
<div style="margin-left:-3rem;" class="slds-truncate" required="true" title="Quantity">Product Description</div>
</th>
<th scope="col" class="slds-size_2-of-12">
<div class="slds-truncate" required="true" title="Quantity">No of times Product Needed</div>
</th>
</tr>
</thead>
<tbody>
<aura:iteration items="{!v.selectedCustomProducts}" var="ct" indexVar="i">
<tr data-record="{!i}" id ="{!i}">
<td role="gridcell">
<div class="slds-truncate" title="Value Proposition">{!ct.ProductName}</div>
</td>
<td role="gridcell">
<div class="slds-truncate" title="Value Proposition">{!ct.ProductDescription}</div>
</td>
<td data-label="Email">
<lightning:input type="text" name="input1" value="{!ct.customProductQuantity }"></lightning:input>
</td>
</tr>
</aura:iteration>
</tbody>
</table>
</lightning:card>
</div>
<footer class="slds-modal__footer">
<lightning:button variant="brand"
label="Confirm"
title="Save"
onclick="{!c.handleConfirmButton}"/>
</footer>
</div>
</section>
<div class="slds-backdrop slds-backdrop_open"></div>
</aura:if>
First Screen JS:
handleConfirmButton : function(component, event, helper){
console.log('>>> handleConfirmButton... ');
let selectedProductList = component.get('v.selectedCustomProducts');
console.log('>>> selectedProductList... '+JSON.stringify(selectedProductList));
let clonedObject = [];
for(var i= 0; i<selectedProductList.length ; i++){
for(var j = 0; j < selectedProductList[i].customProductQuantity-1; j++){
clonedObject.push(JSON.parse(JSON.stringify(selectedProductList[i])));
}
}
let selectedProduct = component.get("v.selectedProducts");
selectedProduct.push(...clonedObject);
console.log('>>> selectedProduct in confirm... '+JSON.stringify(selectedProduct));
//component.set("v.displayEditQuote",true);
component.set("v.isAddProductModalOpen",false);
component.set("v.selectedProducts",selectedProduct);
component.set("v.displayMargin",true);
component.set("v.displayCustomProduct",false);
},
Second Screen HTML:
<aura:attribute name="selectedNotRequiredQuoteLine" type="PriceBookEntryWrapper"/>
<aura:attribute name="selectedQuoteLine" type="PriceBookEntryWrapper" />
<div class="slds-m-around_xx-large">
<!--Use aura:if tag to display/hide popup based on isModalOpen value-->
<aura:if isTrue="{!v.isModalOpen}">
<aura:if isTrue="{!v.displayEditQuote}">
<!-- Modal/Popup Box starts here-->
<section role="dialog" tabindex="-1" aria-labelledby="modal-heading-01" aria-modal="true" aria-describedby="modal-content-id-1" class="slds-modal slds-fade-in-open">
<div class="slds-modal__container">
<!-- Modal/Popup Box Header Starts here-->
<header class="slds-modal__header">
<lightning:buttonIcon iconName="utility:close"
onclick="{! c.closeModel }"
alternativeText="close"
variant="bare-inverse"
class="slds-modal__close"/>
<h2 id="modal-heading-01" class="slds-text-heading_medium slds-hyphenate slds-align_absolute-center">Edit Selected Quote Line Items</h2>
</header>
<!--Modal/Popup Box Body Starts here-->
<div class="slds-modal__content slds-p-around_medium" id="modal-content-id-1">
<aura:if isTrue="{!v.selectedQuoteLine.length > 0}">
<lightning:card title="Required Products">
<table class="slds-table slds-table--bordered ">
<thead>
<tr class="slds-text-title--caps">
<th scope="col" class="slds-size_1-of-12">
<div class="slds-truncate" title="Required">Required</div>
</th>
<th scope="col" class="slds-size_3-of-12">
<div style="margin-left:0 rem;" class="slds-truncate" required="true" title="Product">Product Name</div>
</th>
<th scope="col" class="slds-size_6-of-12">
<div style="margin-left:-3rem;" class="slds-truncate" required="true" title="Quantity">Product Description</div>
</th>
<th scope="col" class="slds-size_2-of-12">
<div class="slds-truncate" required="true" title="Quantity">Quantity</div>
</th>
<th scope="col" class="slds-size_1-of-12">
<div class="slds-truncate" required="true" title="Quantity">List Price</div>
</th>
<th scope="col" class="slds-size_2-of-12">
<div class="slds-truncate" required="true" title="Quantity">Adjusted List Price</div>
</th>
<th scope="col" class="slds-size_2-of-12">
<div class="slds-truncate" required="true" title="Quantity">Total Price</div>
</th>
<th scope="col" class="slds-size_1-of-12">
<div class="slds-truncate" required="true" title="Quantity">Sort Order</div>
</th>
</tr>
</thead>
<tbody>
<aura:iteration items="{!v.selectedQuoteLine}" var="ct" indexVar="i">
<aura:if isTrue="{!!ct.deleted}">
<aura:if isTrue="{!or(not(empty(ct.heading)),!v.selectedIndex == !i)}">
<aura:if isTrue="{!v.isDisplayselectedIndex}">
<tr>
<td></td>
<td>
<div class="slds-size_1-of-2">
<lightning:input type="text" name="input1" value="{!ct.heading}" placeholder="Enter heading here"></lightning:input>
</div>
</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</aura:if>
</aura:if>
<tr data-record="{!i}" id ="{!i}">
<td data-label="Email">
<div class="slds-p-top_none" style="width:1rem;"><lightning:input type="Checkbox" name="{!ct.priceBook.Id}" label="" checked="{!ct.Required}" onchange="{!c.onChangeRequired}"/>
</div>
</td>
<td data-label="Last Name">
<div class="slds-p-top_none slds-p-left_none" style="width: 14rem;margin-left:0 rem">
<lightning:input type="text" name="input1" value="{!ct.priceBook.Product2.Name}"></lightning:input>
</div>
</td>
<td data-label="Email">
<div style="margin-left:-3rem;margin-top: 1.6rem;" aria-label="" class="slds-rich-text-area__content slds-grow slds-cell-wrap slds-p-top_none slds-p-left_none">
<lightning:textarea name="input1" value="{!ct.priceBook.Product2.Description}"/>
</div>
</td>
<td data-label="Email">
<div class="slds-p-top_none" style="width: 1rem;"></div>
<lightning:input type="text" name="input1" value="{!ct.Quantity}" onchange="{!c.onChangeQuantity}"></lightning:input>
</td>
<td data-label="Email">
<ui:outputCurrency class="slds-p-top_none" value="{!ct.priceBook.UnitPrice}" format="{!v.currencyFormatter}"/>
</td>
<td data-label="Email">
<ui:inputCurrency aura:id="amount" class="slds-p-top_none" value="{!ct.adjustedListPrice}" keyup="{!c.onChangeUnitPrice}" format="{!v.currencyFormatter}" updateOn="keyup"/>
</td>
<td data-label="Email">
<div class="slds-p-top_none" style="width: 1rem;"></div>
<lightning:input type="text" name="input1" value="{!ct.adjustedListPrice * ct.Quantity}" readonly="true"></lightning:input>
</td>
<td data-label="Email">
<div class="slds-p-top_none" style="width: 1rem;margin-top: -1rem;"></div>
<lightning:input type="text" name="input1" value="{!ct.sortOrder}"></lightning:input>
</td>
<!--
<td data-label="Email">
<div style="margin-top:1rem;">
<lightning:buttonMenu alternativeText="Show menu" onselect="{! c.handleSelect }">
<lightning:menuItem aura:id="{!i}" value="{!i}" label="Add header above"/>
</lightning:buttonMenu>
</div>
</td>
-->
<td data-label="Email">
<div class="slds-p-top_none" style="margin-top:1rem;">
<lightning:button label="" name="{!ct.priceBook.Id}" iconName="utility:delete" iconPosition="left" variant="destructive" onclick="{! c.onDelete }"/>
</div>
</td>
</tr>
</aura:if>
</aura:iteration>
</tbody>
</table>
</lightning:card>
<p class="slds-align_absolute-center" style="margin-left: 39rem;">Subtotal : {!v.subtotal}</p>
<div><form class="slds-form slds-form_horizontal">
<lightning:input class="slds-size_1-of-4"
style="margin-left: 50rem; text-align: right;"
value="{!v.discount}" label="Discount:"
onchange="{! c.discountValue }"
placeholder="{!v.discount}"
type="number"
name="input1" />
</form>
</div>
<p class="slds-align_absolute-center" style="margin-left: 39rem;">Total : {!v.total}</p>
</aura:if>
</div>
<!--Modal/Popup Box Footer Starts here-->
<footer class="slds-modal__footer">
<lightning:button variant="brand"
label="Previous"
title="Previous"
class="slds-float_left"
onclick="{! c.navigatePreviousScreen }"
/>
<lightning:button variant="neutral"
label="Cancel"
title="Cancel"
onclick="{! c.closeModel }"
/>
<lightning:button variant="brand"
label="Save"
title="Save"
onclick="{!c.saveLineItem}"/>
<lightning:button variant="brand"
label="Sort"
title="Sort"
onclick="{!c.sortLineItem}"/>
</footer>
</div>
</section>
</aura:if>
</aura:if>
</div>
Second Screen JS:
sortLineItem : function(component, event, helper){
var sortAsc = component.get("v.sortAsc");
let sortQuoteLine = component.get('v.selectedQuoteLine');
console.log('>>> sortQuoteLine before sort... '+JSON.stringify(sortQuoteLine));
let sortField = 'sortOrder' ;
if(sortQuoteLine != null && sortQuoteLine.length > 0){
sortQuoteLine.sort(function(a,b){
var t1 = a[sortField] == b[sortField],
t2 = a[sortField] > b[sortField];
return t1? 0: (sortAsc?-1:1)*(t2?-1:1);
});
component.set('v.selectedQuoteLine',sortQuoteLine);
console.log('>>> sortQuoteLine after sort... '+JSON.stringify(sortQuoteLine));
}
let sortNotRequiredQuoteLine = component.get('v.selectedNotRequiredQuoteLine');
if(sortNotRequiredQuoteLine != null && sortNotRequiredQuoteLine.length > 0){
sortNotRequiredQuoteLine.sort(function(a,b){
var t1 = a[sortField] == b[sortField],
t2 = a[sortField] > b[sortField];
return t1? 0: (sortAsc?-1:1)*(t2?-1:1);
});
component.set('v.selectedNotRequiredQuoteLine',sortNotRequiredQuoteLine);
}
}