[SalesForce] How to convert a Visualforce apex:pageMessages to be lightning style

During my working on converting existing pages to be lightning experience style (as known as slds style). One of the challenges I have faced is to convert <apex:pageMessages/> . Usually the controller side of code is something like below:

public class ConvertPageMessagesController{
    public ConvertPageMessagesController(){
        ApexPages.addmessage(new ApexPages.message(ApexPages.severity.FATAL,'Please enter Account name'));
        ApexPages.addmessage(new ApexPages.message(ApexPages.severity.ERROR,'Please enter Account number'));
        ApexPages.addmessage(new ApexPages.message(ApexPages.severity.WARNING,'Please enter Account phone'));
        ApexPages.addmessage(new ApexPages.message(ApexPages.severity.INFO,'Please enter Account site'));
        ApexPages.addmessage(new ApexPages.message(ApexPages.severity.CONFIRM,'Please enter Account industry'));
    }
}

There are definitely walkaround on this. I can use a page_message and a serverity_level property and check the page status and the page message and use front-end code to handle the logic. But the code will inevitable be long and tedious. Is there a good way of handling this?

Best Answer

Here is what I do:

Class used by all my controllers:

VF Messages Abstract:

public abstract class VF_Messages_Abstract {


    public void createError(ApexPages.Severity s, String message) {
        ApexPages.addMessage(
                New ApexPages.Message(
                        s, string.escapeSingleQuotes(message.escapeJava())
                )
        );

    }

    /**@description Indicates if a custom message is present*/
    public boolean hasMessages {
        get {
             return ApexPages.hasMessages();
        }
    }

    /**@description The custom error message */
    public String errorMessage {
        get {
            if (hasMessages) {
                return ApexPages.getMessages()[0].getDetail();
            }

            return null;
        }
    }

    /**@description The type of message: 'error' or 'success' */
    public string alertType {
        get {
            if (hasMessages) {
                return ApexPages.getMessages()[0].getSeverity() == ApexPages.Severity.CONFIRM ? 'success' : 'error';
            }

            return 'error';
        }
        private set;
    }



}

All controller for VF extend this class

Then in my vf pages I use the following:

Messages Toast

    <!-- ERROR ALERT DIV -->
    <apex:outputPanel layout="block" id="msg_block" style="display: none;">
        <div id="err_wrapper"
             class="slds-notify slds-notify--alert slds-theme--{!alertType} slds-theme--alert-texture"
             role="alert">
            <h2>
                <div xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
                    <svg aria-hidden="true"
                         class="slds-icon icon-text-email slds-icon--small slds-m-right--x-small">
                        <use xlink:href="{!URLFOR($Resource.SLDS, '/assets/icons/utility-sprite/svg/symbols.svg#' + if(alertType = 'success','check','ban'))}"></use>
                    </svg>
                    <span id="err_text"></span>
                </div>
            </h2>
        </div>

    </apex:outputPanel>

Helper Panel

        <!--APEX VARIABLES DIV-->
        <apex:outputPanel id="post_processing">

            <script>

                var hasMessages = {!hasMessages};
                var errorMessage = "{!errorMessage}";

                checkMessages();

            </script>

        </apex:outputPanel>

Check Messages Code (Using jQuery)

function checkMessages() {
    if (hasMessages) {
        $('#err_text').html(errorMessage);
        $('[id$=msg_block]').show();
    } else {
        $('[id$=msg_block]').hide();
    }

}

My buttons, action functions, etc rerender the post_processing and msg_block

Creating an error In the controller when I catch or want to display an error I simply:

createError(ApexPages.Severity.[ERROR | CONFIRM],YOURMESSAGEHERE);

This allows me to control the messages, when to display it and which theme to show.

Note: The xmlns= on the div containing the SVG is a MUST as if you try to rerender without it the page will simply stall. Important trick to remember for anytime you are re rendering a container containing an SLDS SVG

If you need a example all put together let me know.

End result is (Error):

enter image description here

Or (Confirm)

enter image description here

I also have implemented a way to pass messages between transactions so if you need to say DML on button click and then Callout oncomplete of button click, if there was an error in the first step, when the second step happens it does not clear the message like it normally would (not shown in code)