2

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.

3
  • what is/are the error(s) ? can you provide debugging details?
    – glls
    Jun 5, 2018 at 14:57
  • It just printed this in console.log Problem saving record, error: [{"fieldErrors":{},"pageErrors":[]}]. My console statement on handleRecordUpdate is not working.
    – AjaySFDC
    Jun 5, 2018 at 15:08
  • please edit your post rather than adding info in the comments. Thanks
    – glls
    Jun 5, 2018 at 15:08

1 Answer 1

0

I'm not sure that this will accomplish what you think it will:

I thought of using <Force:recordData>'s SaveRecord feature, so as to not to call Server side again.

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:

public Case_Fulfilment__c updateStatus(Case_Fulfilment__c record) {
    record.status__c = 'completed';

    try {
        update record;
        return record;
    } catch (Exception e) {
        return null;
    }

    return null; // I believe there are some issues with the compiler that will require an extra return here.
}

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):

 var allFulls = component.get("v.AllFulfillments");
 allFulls[index] = result;
 component.set("v.AllFulfillments", allFulls);

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.

3
  • I tried this. the refresh is not happening on the Init() after this update. <force:recordData> does that without any additional calls. I wanted to know why in my code <force:recordData> is not getting called.
    – AjaySFDC
    Jun 5, 2018 at 15:17
  • You're code is getting called, that's why you get the debug. I updated my answer to explain what you can do to fix your error, but you're putting entirely too much effort into this. And of course it doesn't update on the init because it doesn't reinitialize the component, it shouldn't re-initialize the component. You're writing a bunch of extra code and running into a bunch of errors just to avoid writing a little bit of extra code.
    – gNerb
    Jun 5, 2018 at 15:19
  • Updated my answer again.
    – gNerb
    Jun 5, 2018 at 15:23

You must log in to answer this question.

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