I'm facing trouble with <force:recordData>
.
I have a list of custom objects displayed in the form of table over <Aura:iteration>
Out of that list, when a button is clicked, a certain field status needs to be changed.
The user should be able to click multiple times without having to load the page multiple times.
Only the status needs to be updated to the record each time.
I thought of using <Force:recordData>
's SaveRecord feature, so as to not to call Server side again.
But <Force:recordData>
is not getting called.
Here is my code :
(adding only the relevant code here)
Component Markup :
<aura:component controller="QAC_FulfillmentController" implements="flexipage:availableForAllPageTypes,force:hasRecordId">
<aura:handler name="init" action="{!c.doInit}" value="{!this}" />
<aura:attribute name="AllFulfillments" type="Case_Fulfilment__c[]" />
<aura:attribute name="eachFulfillment" type="Case_Fulfilment__c" />
<force:recordData aura:id="recordHandler"
recordId="{!v.eachFulfillment.Id}"
targetRecord="{!v.eachFulfillment}"
targetFields="{!v.eachFulfillment}"
mode="EDIT"
recordUpdated="{!c.handleRecordUpdated}"
/>
<article class="slds-card">
<div class="slds-card__body">
<div class="slds-card__body--inner">
<div class="slds-tile">
<table class="slds-table slds-table_bordered slds-table_cell-buffer">
<thead class="tableHead">
<tr>
<th scope="col"><div class="slds-truncate" title="Status Flag">Status Flag</div></th>
<th scope="col"><div class="slds-truncate" title="Action">Action</div></th>
</tr>
</thead>
<tbody>
<aura:iteration items="{!v.AllFulfillments}" var="wrap" indexVar="idx">
<tr>
<th scope="row">
<aura:if isTrue="{!wrap.Status__c == 'Success'}">
<div class="slds-truncate" title="{!wrap.Status__c}">
<img src="/img/samples/light_green.gif" />
</div>
</aura:if>
<aura:if isTrue="{!wrap.Status__c == 'Failed'}">
<div class="slds-truncate" title="{!wrap.Status__c}">
<img src="/img/samples/light_red.gif" />
</div>
</aura:if>
<aura:if isTrue="{!wrap.Status__c == 'Pending'}">
<div class="slds-truncate" title="{!wrap.Status__c}">
<img src="/img/samples/light_yellow.gif" />
</div>
</aura:if>
</th>
<th scope="row">
<div class="slds-dropdown-trigger slds-dropdown-trigger_click">
<button class="slds-button slds-button_icon slds-button_icon-border-filled slds-button_icon-x-small"
aria-haspopup="true" title="Change Status"
onclick="{!c.toggleMenu}" data-custom="{!idx}">
<span>
<lightning:icon iconName="utility:success" size="x-small"/>
</span>
<span class="slds-assistive-text">Mark as Completed</span>
</button>
</div>
</th>
</tr>
</aura:iteration>
</tbody>
</table>
</div>
</div>
</div>
</article>
</aura:component>
Javascript Controller :
({
doInit : function(component, event, helper) {
var action = component.get("c.getAllFFRecords");
// Logics to set V.allFulfillments
},
toggleMenu : function(component, event, helper) {
console.log("inside toggle");
var selectedItem = event.currentTarget;
var index = selectedItem.dataset.custom;
console.log('rec index: ' + index);
var selectedFF = component.get("v.AllFulfillments")[index];
console.log("Selected FF :" + JSON.stringify(selectedFF));
selectedFF.Status__c = 'Success';
component.set("v.eachFulfillment", selectedFF);
var updatedFF = component.get("v.eachFulfillment");
console.log("Selected FF :" + JSON.stringify(updatedFF));
// update FF prints the changed status
helper.recordUpdate(component, event);
},
handleRecordUpdated : function(component, event, helper){
// this is not getting called at all
console.log('inside force record data');
var eventParams = event.getParams();
if(eventParams.changeType === "LOADED"){
console.log("record is loaded");
}
if(eventParams.changeType === "CHANGED") {
var changedFields = eventParams.changedFields;
console.log('Fields that are changed: ' + JSON.stringify(changedFields));
// record is changed, so refresh the component (or other component logic)
}
}
})
helper Controller :
(it throws error)
({
recordUpdate : function(component, event){
console.log("inside update");
component.find("recordHandler").saveRecord($A.getCallback(function(saveResult) {
if (saveResult.state === "SUCCESS" || saveResult.state === "DRAFT") {
console.log("success");
} else if (saveResult.state === "INCOMPLETE") {
console.log("User is offline, device doesn't support drafts.");
} else if (saveResult.state === "ERROR") {
console.log('Problem saving record, error: ' + JSON.stringify(saveResult.error));
} else {
console.log('Unknown problem, state: ' + saveResult.state + ', error: ' + JSON.stringify(saveResult.error));
}
}));
}
})
It just printed this in console.log Problem saving record, error: [{"fieldErrors":{},"pageErrors":[]}]
. My console statement on handleRecordUpdate is not working.
Best Answer
I'm not sure that this will accomplish what you think it will:
The <force:recordData> tag will still make a call to the server. There's no way for it to save to the server without a call. There is no point in trying to avoid a call to the server.
Don't bother using <force:recordData>. Create a method in your apex controller that does the save:
Then you can call this method from your helper.
Update based on your comment
It shouldn't re-initialize your component, that would defeat the purpose of asynchronous code. Instead, using my method you get the updated record back from the save and can use it to set an attribute in the component which will trigger a re-render event automatically.
It should be something simple like (obviously not 100% correct code but gets the point across):
Update based on your update
Based on your error, I would check the developer console debug logs after you attempt a save. Chances are that is where you will find the error causing your problem.