[SalesForce] apex:ActionFunction not reRendering or showing status

Not sure what is happening here. I am unable to show the spinner status or reRender the page with updated data. I did see this information about reRendering with conditionals but I am reRendering my entire form and it is still not working. The spinner only works if I put the status on the actual button, but I have never had to build an actionFunction like that before.

Unsuccessful Solutions I have tried:

  • Refreshing page via PageReference on the testErrorHandling() method
  • javascript remoting
  • button, apex:commandLink, apex:commandButton
  • putting the spinner status on the button rather then the actionFunction
  • combining an onClick and an action attribute to the button
  • returning data with the pullCredit() method
  • not returning data with the pullCredit() method
  • directly calling the pullCredit() mehtod from the vfp
  • put the whole VFP in the "stop" facet of the actionStatus

nothing seems to work which leads me to believe it is a rule about how I have written conditionals in my VFP. Can anyone see what is happening?

VFP:

<apex:page id="EquifaxCreditPullPage" showHeader="true" standardController="Lead" extensions="EquifaxCreditPullController">
    <head>
    <apex:stylesheet value="{!URLFOR($Resource.SLDS2018, 'styles/salesforce-lightning-design-system.css')}" />

    <style>
    .not-active {
          pointer-events: none;
          cursor: default;
          text-decoration: none;
          color: black;
     }
    </style>
    <script>
    function pullCredit() {
        var leadId = '{!Lead.Id}';
        var contactId = null;
        var creditReviewId = null;
        Visualforce.remoting.Manager.invokeAction(
            '{!$RemoteAction.EquifaxCreditPullController.pullCred}',
            leadId, contactId, creditReviewId,
            function(result, event){
                alert('complete!!' + result);
                console.log('result:: ' + result);
            }
        );
    };
    </script>
    </head>

<apex:form id="theForm">
    <apex:actionFunction name="pullCreditActionFunction" action="{!testErrorHandling}" onComplete="alert('completed on action function')" status="spinnerStatusCredit" reRender="theForm"/>
    <apex:pageMessages />

    <table class="slds-table slds-table--bordered slds-table--cell-buffer">
        <thead>
        <tr class="slds-text-title--caps">
            <th scope="col">
                <div class="slds-truncate" title="First Name">Name</div>
            </th>
            <th scope="col">
                <div class="slds-truncate" title="Status">Status</div>
            </th>
            <th scope="col">
                <div class="slds-truncate" title="Action">Action</div>
            </th>
        </tr>
        </thead>
        <tbody>
        <apex:repeat value="{!leadCCSMap}" var="contactOrLead">
            <tr>
                <th scope="row" data-label="Name">
                    <div class="slds-truncate" title="Name">{!contactOrLead.Name}</div>
                </th>
                <td data-label="Status">
                    <div class="slds-truncate" title="Status">{!IF(emptyCCS, 'Awaiting Pull Request', leadCCSMap[contactOrLead].Status__c)}</div>
                </td>
                <td data-label="Action" id="pullCreditButton">
                    <apex:commandButton onClick="pullCreditActionFunction()" value="Pull Credit" onComplete="alert('completed on button')"/>                        
                    <apex:actionStatus id="spinnerStatusCredit">
                       <apex:facet name="start">
                        <apex:outputPanel>
                          <apex:outputPanel layout="block"/>
                            <apex:outputPanel layout="block">
                            <img src="/img/loading24.gif" style="vertical-align:middle; horizontal-align:middle"/>
                            <span>Please wait...</span>
                          </apex:outputPanel>
                        </apex:outputPanel>
                      </apex:facet>
                   </apex:actionStatus>
                </td>
            </tr>
        </apex:repeat>
        </tbody>
    </table>
</apex:form>
</apex:page>

APEX:

global class EquifaxCreditPullController {

public List<Consumer_Credit_Summary__c> cc{get;set;}
public List<Contact> acctContact{get;set;}
public Map<Contact, Consumer_Credit_Summary__c> contactCCSMap {get;set;}
public Map<Lead, Consumer_Credit_Summary__c> leadCCSMap {get;set;}
public Boolean emptyCCS {get;set;}

public EquifaxCreditPullController(ApexPages.StandardController controller){
    //code that fills in data if it is available on page load 
}

@RemoteAction
global static string pullCred(String leadId, String contactId, String creditReviewId) {
    String status;
    ApexPages.Message msg;
    String jsonBody = '{"LeadId" : "' + leadId + '" }';
    ....webservice callout....
        JSONParser parser = JSON.createParser(res.getBody());
        while (parser.nextToken() != null) {
            if ((parser.getCurrentToken() == JSONToken.FIELD_NAME) && (parser.getText() == 'ResultStatus')) {
                parser.nextToken();
                status = parser.getText();
            }
        }
        if(status == 'Success'){
            system.debug('got into Success:: ' + status);
        }
        else if(status == 'CriticalError'){
            msg=new ApexPages.Message(ApexPages.Severity.ERROR, 'CriticalError');
            ApexPages.addMessage(msg);
        }
        else if(status == 'NotImplemented'){
            msg=new ApexPages.Message(ApexPages.Severity.ERROR, 'NotImplemented');
            ApexPages.addMessage(msg);
        }
        else {
            msg=new ApexPages.Message(ApexPages.Severity.ERROR, 'TBD');
            ApexPages.addMessage(msg);
        }
        return status;
    }
    catch (System.CalloutException z) {
        return null;
    }
}

public void testErrorHandling(){
    Id currentPageId = ApexPages.currentPage().getParameters().get('id');
    pullCred(currentPageId, null, null);
}
}

Best Answer

Based on discussion on comments there are 3 issues:

Issue 1

Your action status does not show because it is a child of the TD element. This poses two potential issues

  1. The TD element may not get rendered at all meaning your status will never appear on the page and thus cannot be used in an action function.
  2. The status component could get rendered multiple times confusing the page.

To fix this, simply make your status a child of the apex:form tag.

Issue 2

I believe there is a chance that the oncomplete calls in your action function and button are interfering with or possibly overriding the re-render call. Try removing those and see if the re-render begins to work

Issue 3

You need to make sure the list you are iterating over contains the updated data before the re-render is called. This can be accomplished by

  • directly modifying the record in the list
  • Removing the record and re-adding it to the list after updating it
  • requerying for the entire dataset once your method is completed

Alternatively, if you get rid of the re-render altogether, the page will do a full refresh which would recall your constructor.

Related Topic