I have over 2000 checkboxes in my lightning component and the componet loads within 6 seconds. However when saving Salesforce Lightning crawls and takes a minute on my machine to save and for our QA Tester it is taking over two minutes to save. The back end is only taking 300 milliseconds.
Here is the log for the front end:
JSON.stringify: 257.11669921875ms
FRCElementMatrixComponent.js:246 JSON.parse: 26.737060546875ms
FRCElementMatrixComponent.js:261 filter: 4.0048828125ms
FRCElementMatrixComponent.js:278 clear v.elements: 4213.22509765625ms
FRCElementMatrixComponent.js:287 saveAction: 32226.1650390625ms
FRCElementMatrixComponent.js:331 loadElementMatrixData: 12743.0830078125ms
Here is the code for the controller:
var saveAction = component.get("c.saveElements");
console.time('JSON.stringify');
var allJson = JSON.stringify(component.get("v.elements"));
console.timeEnd('JSON.stringify');
console.time('JSON.parse');
var allObj = JSON.parse(allJson);
console.timeEnd('JSON.parse');
//Only save elements that are enabled and that have changed
function checkElement(element) {
if (element.checkboxDisabled)
return false;
if (element.IsGroupRow)
return false;
return element.Renovated != element.RenovatedOriginal;
}
console.time('filter');
var onlyEnabledObj = allObj.filter(checkElement);
var onlyEnabledJson = JSON.stringify(onlyEnabledObj);
console.timeEnd('filter');
//Clear everything because it results in less save time
allJson = null;
allObj = null;
console.time('clear v.elements');
component.set("v.elements", []);
console.timeEnd('clear v.elements');
saveAction.setParams({
accountId : component.get("v.recordId"),
elementsJson : onlyEnabledJson
});
saveAction.setCallback(this, function(a) {
if (a.getState() === "SUCCESS") {
console.timeEnd('saveAction');
//We have to load after we save to re-calculate everything
var loadAfterSaveAction = component.get('c.doLoadAfterSave');
$A.enqueueAction(loadAfterSaveAction);
} else if (a.getState() === "ERROR") {
$A.log("Errors", a.getError());
}
});
console.time('saveAction');
$A.enqueueAction(saveAction);
Here is the UI for a normal element checkbox, not at the Area or Good Type level:
<!-- Normal Element Checkbox -->
<aura:If isTrue="{#and(!element.IsGroupRow, element.CheckboxDisabled)}">
<div class="elementPeriod" data-columnType="{#element.RenovationStatus}" data-groupId="{#element.GoodType}" data-areaId="{#element.Area}">
<ui:outputCheckbox aura:id="elementCheckboxDisabled" value="{#element.Renovated}" />
</div>
</aura:If>
<aura:If isTrue="{#and(!element.IsGroupRow, !element.CheckboxDisabled)}">
<div class="elementPeriod" data-columnType="{#element.RenovationStatus}" data-groupId="{#element.GoodType}" data-areaId="{#element.Area}">
<!-- The hidden id is inside the class name since we are already using the id and name for grouping -->
<ui:inputCheckbox aura:id="elementCheckbox" class="{#element.HiddenId}" name="{#element.GroupId}" value="{#element.Renovated}" click="{!c.handleCheckboxClick}" />
</div>
</aura:If>
lightning:datatable
is already prepped for infinite loading){! v.myVariable}
is binded and will "stay up to date" as the values adjust on it - this is very expensive. Using{# v.myVariable}
is much lighter. Read more here