1

I am working on project to convert VF components into LWC. I have inserted the LWC in VF page using lightning out. The toast is showing up only in lightning experience and not in VF page. ApexPages.addMessage() is giving error: "ApexPages.addMessage can only be called from a Visualforce page". Due to this, I am not able to display warnings or errors in the VF page either as a toast or as a apex message.

I tried checking the theme using String theme = UserInfo.getUiThemeDisplayed(); before display toast or apex message but that isn't working too. Please guide. Thanks!

Screenshot of error Error

Apex snippet

        String theme = UserInfo.getUiThemeDisplayed();
        if(checkMemberOfRecord.size()!=0 && contactRole.contains('Member of Record')){
            if(theme!='Theme4d'){
                ApexPages.addMessage( new ApexPages.Message(ApexPages.Severity.ERROR, 'Account cannot have multiple Member of Records.'));
            }
            return 'fail';
        }
11
  • Just to clarify - you need this to work in Classic as well as Lightning? If it only needs to work in a lightning context, then using the LWC show toast methods are the way to go Dec 16, 2019 at 8:42
  • @BrianMiller I need this to work only in Classic
    – Koustubh
    Dec 16, 2019 at 8:45
  • Do you need to display only Error messages?
    – ytiq
    Dec 16, 2019 at 8:46
  • Is the Apex being called from the LWC code or from a VF controller? Calling it from the VF controller shouldn't cause an error Dec 16, 2019 at 8:46
  • @BrianMiller Apex is being called from LWC wire
    – Koustubh
    Dec 16, 2019 at 8:48

2 Answers 2

2

it's correct you cannot use ApexPage.addMessage in LWC. But there are a few good replacements.

If you want only to display only error messages you can just throw AuraHandledException(message); for your error messages.

// ApexClass.class
public class Controller {
    @AuraEnabled
    public static void someMethod() {
        Boolean isError = true;
        if (isError) {
            throw new AuraHandledException('Error message');
        }
    }
}
<!-- component.html -->
<template>
   <c-toast></c-toast>
   <!-- Some other markup -->
</template>
// component.js
// ...
import someMethod from '@salesforce/apex/Controller.someMethod';
// ...
export default class Component extends LightningElement {
    @wire(someMethod)
    callSomeMethod({error, data}) {
        if (data) {
            // process results
        } else if (error) {
// this.template.query() seems not valid for LWC use this.template.querySelector as below            
//this.template.query('c-toast').show(error.message || error.body.message, 'error');
this.template.querySelector('c-toast').show(error.message || error.body.message, 'error');

        }
    }
}

For displaying messages you can use Custom Toast if you want. Can provide code if needed.

UPDATE

<!-- toast.html -->
<template>
    <div class="toast toast_hide" style="height:4rem" data-id="toast">
        <div class="slds-notify_container slds-is-relative">
            <div class={notifyClasses} role="status">
                <span class="slds-assistive-text">error</span>
                <lightning-icon icon-name={iconName} alternative-text={type}></lightning-icon>
                <div class="slds-notify__content">
                    <h2>{title}</h2>
                    <p>{message}</p>
                </div>
                <div class="slds-notify__close">
                    <lightning-button-icon icon-name="utility:close" alternative-text="Close"></lightning-button-icon>
                </div>
            </div>
        </div>
    </div>
</template>
//toast.js
import {LightningElement, api, track} from 'lwc';

export default class UmToast extends LightningElement {

    @track
    message;
    @track
    title;
    @track
    type;

    @api
    show(message, type) {
        this.title = 'error';
        this.message = message;
        this.type = type || 'error';

        const toast = this.template.querySelector('.toast');
        toast.classList.toggle('toast_show');
        toast.classList.toggle('toast_hide');

        this.timer = setTimeout(() => {{
            toast.classList.toggle('toast_show');
            toast.classList.toggle('toast_hide');
        }}, 3000);
    }

    get notifyClasses() {
        return `slds-notify slds-notify_toast slds-theme_${this.type}`;
    }
    get iconName() {
        return `utility:${this.type}`;
    }
}
/* toast.css */
.toast {
  -webkit-transition: opacity 1s ease-in-out;
  transition: opacity 1s ease-in-out;
}

.toast_hide {
  opacity: 0;
}

.toast_show {
  opacity: 1;
}
6
  • Seems like this can work. Please provide the code if you can. Many thanks!
    – Koustubh
    Dec 16, 2019 at 8:54
  • Ok I'll add code for Custom toast in a few minutes also
    – ytiq
    Dec 16, 2019 at 8:59
  • 1
    @Koustubh Using throw new AuraHandledException() is definitely the way to go! Dec 16, 2019 at 9:00
  • @Koustubh Added code for Custom toast which can be used in VF and also updated code for component to use that code.
    – ytiq
    Dec 16, 2019 at 9:05
  • @Koustubh Do you need any more assistance?
    – ytiq
    Dec 16, 2019 at 9:12
0

A modal for showing error will be the easiest way. enter image description here

HTML

<template if:true={showErrorModal}>
            <section role="dialog" tabindex="-1" aria-labelledby="modal-heading-01" aria-modal="true"
                aria-describedby="modal-content-id-1" class="slds-modal slds-fade-in-open">
                <div class="slds-modal__container">
                    <!-- modal header start -->
                    <header class="slds-modal__header">
                        <button class="slds-button slds-button_icon slds-modal__close slds-button_icon-inverse"
                            title="Close" onclick={closeErrorModal}>
                            <lightning-icon icon-name="utility:close" alternative-text="close" variant="inverse"
                                size="small">
                            </lightning-icon>
                        </button>
                        <h2 id="modal-heading-02" class="slds-text-heading_medium slds-hyphenate">{errorMessage}</h2>
                        </br>
                        <div style="text-align:center;">
                            <lightning-button class="slds-m-top_small" variant="brand" label="Close"
                                onclick={closeErrorModal}></lightning-button>
                        </div>
                    </header>
                </div>
            </section>
            <div class="slds-backdrop slds-backdrop_open"></div>
        </template>

JAVASCRIPT

@track errorMessage;
@track showErrorModal=false;
handleSubmit(event) {
        // closing modal and showing loading spinner
        this.bShowModal = false;
        this.showLoadingSpinner = true;

        // calling apex class method to save new relationship to database and passing required parameters to the function
        saveAccount()
            .then(result => {

            })
            .catch(error => {
                this.errorMessage = error.body.message;
                this.showErrorModal = true;
            });
    }

APEX

       if(contactRole==null){
            throw new AuraHandledException('Please select atlease one Contact Role');
        }

You must log in to answer this question.

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