function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
MarkHBMarkHB 

Can I delay the redirect from a visualforce controller?

Hi,
I am working on a new Visualforce page as part of our Lightning conversion.  As part of that, I've written code to showMessages if we're still on Classic, and showToasts if we're on Lightning.  If the operation succeeds, I would like to show a Success message and then redirect back to the record page, but the redirect happens instead of the rerender (for failure, I return null as the new pageReference so no redirect happens and the messages display properly).  How can I force the VF page to wait for the showToast operation(s) to complete before reloading the record?

VF page:
<apex:page id="Xx_CancelQuote"
           standardController="xx__Quote__c"
           extensions="XxQuoteButtonController"
           title="Cancel Quote"
           lightningStylesheets="{!lightning}">
    <apex:slds />
    <apex:form >
        <apex:actionFunction name="cancelQ" action="{!cancelQuote}" id="cancelFunction" reRender="messageBox" />
        <apex:actionFunction name="return2Q" action="{!returnToRecord}" id="returnFunction" />
    </apex:form>
    <apex:outputPanel id="scriptPanel">
        <script>if (confirm("Cancel quote {!quoteNumber}?"))
                cancelQ();
            else
                return2Q();
        </script>
    </apex:outputPanel>
    <apex:outputPanel id="messageBox">
        <apex:pageMessages showDetail="true"/>
        <script>
            <apex:repeat value="{!toastMessages}" var="dirKey">
            sforce.one.showToast({
                "title":  "{!toastMessages[dirKey].title}",
                "message":  "{!toastMessages[dirKey].message}",
                "type":  "{!toastMessages[dirKey].typeName}",
                "mode":  "{!toastMessages[dirKey].mode}"
            });
            </apex:repeat>
        </script>
    </apex:outputPanel>
    <br/>
    <apex:form>
        <apex:commandButton id="returnBtn" value="Return to Quote" onClick="return2Q(); return false;" />
    </apex:form>
</apex:page>

Controller:
/**
 * 
 * Controller for Convert-Xx_-to-Lightning buttons
 */

public with sharing class Xx_QuoteButtonController {
    ApexPages.StandardController stdCon;

    public class ToastMessage {
        public String typeName {get; set;}
        public String title {get; set;}
        public String message {get; set;}
        public String mode {get; set;}

        ToastMessage(String typeName, String title, String message, String mode) {
            this.typeName = typeName;
            this.title = title;
            this.message = message;
            this.mode = mode;
        }
    }

    public Map<Integer, ToastMessage> toastMessages {get;set;}

    public Boolean lightning;

    public Integer getMessageSize() {
        return this.toastMessages.size();
    }

    public Xx_QuoteButtonController(ApexPages.StandardController controller) {
        stdCon = controller;
        toastMessages = new Map<Integer, ToastMessage>();
    }

    //There is probably a much better way to do this
    public String getQuoteNumber() {
        String quoteNumber = '(Name not available)';
        xx__Quote__c quote = (xx__Quote__c) stdCon.getRecord();
        quote = [SELECT Id, QuoteNumber__c FROM xx__Quote__c WHERE Id = :quote.Id];
        if (quote != null && quote.QuoteNumber__c != null && !(quote.QuoteNumber__c.equals('') || quote.QuoteNumber__c.isWhitespace())) {
            quoteNumber = quote.QuoteNumber__c;
        }
        return quoteNumber;
    }

    public PageReference returnToRecord() {
        return stdCon.view();
    }

    public PageReference cancelQuote() {
        PageReference result;
        Id cancelledRecordTypeId = Schema.SObjectType.xx__Quote__c.getRecordTypeInfosByName().get('Cancelled').getRecordTypeId();
        try {
            xx__Quote__c quote = (xx__Quote__c) stdCon.getRecord();
            if (Test.isRunningTest()) {
                xx__Quote__c quote2 = [SELECT Id, Name FROM xx__Quote__c WHERE Id = :quote.Id];
                if (quote2.Name.equals('BAD')) {
                    Exception e = new NoDataFoundException();
                    e.setMessage('Bad record found!');
                    throw e;
                }
            }
            if (quote != null) {
                quote.xx__Status__c = 'Cancelled';
                quote.RecordTypeId = cancelledRecordTypeId;
            }
            result = stdCon.save();
            addPageMessage(ApexPages.Severity.CONFIRM, 'Success!', 'Record was cancelled');
        } catch (Exception e) {
            String errorName = logError(e, 'Cancel Xx_ Quote');
            addPageMessage(ApexPages.Severity.ERROR, 'Cancellation Failed!', e.getMessage());
            result = null;
        }
        return result;
    }

    public Boolean getLightning() {
        return UserInfo.getUiThemeDisplayed().toLowerCase().startsWith('theme4');
    }

    private void addPageMessage(ApexPages.Severity severity, String message, String detail) {
        if (getLightning()) {
            String severityName;
            String mode = 'sticky';
            switch on severity {
                when CONFIRM {
                    severityName = 'success';
                    mode = 'dismissable';
                }
                when WARNING {
                    severityName = 'warning';
                }
                when ERROR,FATAL {
                    severityName = 'error';
                }
                when INFO {
                    severityName = 'info';
                }
                when else {
                    severityName = 'other'; //should never get here
                }
            }
            toastMessages.put(toastMessages.size(), new ToastMessage(severityName, message, detail, mode));
            System.debug('Adding toast '+toastMessages.size()+': '+severityName+', '+message+', '+detail+', '+mode);
        } else { //classic
            ApexPages.addMessage(new ApexPages.Message(severity, message, detail));
        }
    }

    private static String logError(Exception e, String applicationFunction) {

        //Omitted, writes the exception to a tracking object and returns the Name of the record created.
}
}
Thanks for any advice you can give!
 
ShirishaShirisha (Salesforce Developers) 
Hi Mark,

Greetings!

You can include a javascript snippet at the top of the page to redirect to another url after 5 seconds.

<script type="text/javascript">
    window.setTimeout("redirectpage();", 5000);    
    function redirectpage(){
    window.top.location.href = 'http://www.redirectpageurl.com';
    }
</script>

Kindly let me know if it helps you and close your query by marking it as solved so that it can help others in the future.

Warm Regards,
Shirisha Pathuri