Tuesday, 1 June 2021

Error handling Custom Lightning web component

 On the backend, the component javascript detects the type of error object it receives. Depending on which process fails, 

the error object will look slightly different. We are involving some logic here to ensure we drill down to the error message 

and details that are relevant.


//lwcErrorHandling.html 


<template>

  <!--banner-->

  <div class="slds-notify slds-notify_alert slds-theme_alert-texture slds-theme_error" role="alert">

    <!--error graphic-->

    <span class="slds-icon_container slds-icon-utility-error slds-m-right_x-small" title="Description of icon when needed">

      <lightning-icon icon-name="utility:error" alternative-text="Error" title="Error" variant="inverse"></lightning-icon>

    </span>

    <!--error message-->

    <h2>{errorMessageToDisplay}</h2>

    <!--close button-->

    <div class="slds-notify__close">

      <button class="slds-button slds-button_icon slds-button_icon-small slds-button_icon-inverse" title="Close" onclick={closeError}>

        <lightning-icon icon-name="utility:close" alternative-text="Close" title="Close" variant="inverse"></lightning-icon>

      </button>

    </div>

  </div>

</template>


//lwcErrorHandling.js


import { LightningElement, api, track } from 'lwc';


export default class LwcErrorHandling extends LightningElement {

    @api error;

    errorMessageToDisplay = '';


    // this runs every time this component is loaded

    connectedCallback(){

        this.errorMessageToDisplay = 'An error occurred \n';

        console.log(this.error);

        

        // getting meaningful error message depending on error type

        // handles errors from wire & regular apex methods

        if(this.error.body){

            if (Array.isArray(this.error.body)) {

                this.errorMessageToDisplay += this.error.body.map(e => e.message).join(', ');

            }

            else if(typeof this.error.body === 'object'){

                let fieldErrors = this.error.body.fieldErrors;

                let pageErrors = this.error.body.pageErrors;

                let duplicateResults = this.error.body.duplicateResults;

                let exceptionError = this.error.body.message;


                if(exceptionError && typeof exceptionError === 'string') {

                    this.errorMessageToDisplay += exceptionError;

                }

                

                if(fieldErrors){

                    for(var fieldName in fieldErrors){

                        let errorList = fieldErrors[fieldName];

                        for(var i=0; i < errorList.length; i++){

                            this.errorMessageToDisplay += errorList[i].statusCode + ' ' + fieldName + ' ' + errorList[i].message + ' ';

                        }

                    }

                }

        

                if(pageErrors && pageErrors.length > 0){

                    for(let i=0; i < pageErrors.length; i++){

                        this.errorMessageToDisplay += pageErrors[i].statusCode + ' '+ pageErrors[i].message;

                    }

                }

        

                if(duplicateResults && duplicateResults.length > 0){

                    this.errorMessageToDisplay += 'duplicate result error';

                }

            }  

        }

        // handles errors from the lightning record edit form

        if(this.error.message){

            this.errorMessageToDisplay += this.error.message;

        }

        if(this.error.detail){

            this.errorMessageToDisplay += this.error.detail;

        }


    }


    // runs when the close button on the error banner is clicked

    closeError() {

        // reset variables

        this.errorMessageToDisplay = '';

        this.error = null;

        // create a custom event for resetting the error state

        const closeErrorEvent = new CustomEvent("errorclosed", {

          detail: this.error

        });

    

        // dispatch the custom event to the parent component, this resets the error and hides this component

        // if the parent component triggers another error, this entire component loads again and runs through the connectedCallback logic

        this.dispatchEvent(closeErrorEvent);

      }

}



//accountinfo.html :



<template>


    <!-- error handling -->

    <template if:true={error}>

        <c-errorhandling error={error} onerrorclosed={handleError}></c-errorhandling>

    </template>


    <lightning-card  title="Account Info" icon-name="standard:account">

        <div class="slds-p-around_small">

            <!-- record edit form-->

            <lightning-record-edit-form record-id={recordId} object-api-name="Account" onerror={handleFormError}>

                    <lightning-input-field field-name='Name'></lightning-input-field>

                <!-- submit button -->

                <lightning-button class="slds-m-top_small button-fixed" variant="brand" type="submit" name="save" label="Save"></lightning-button>

            </lightning-record-edit-form>


            <!-- child component -->

            <c-accountinfochild></c-accountinfochild>

        </div>       

    </lightning-card>

</template>



// accountinfo.js


import { LightningElement, api } from 'lwc';


export default class Accountinfo extends LightningElement {

    @api recordId;

    error;

    

    // handle error from child components

    errorCallback(error, stack){

        this.error = error;

    }

    

    // handle errors from self (submit button press)

    handleFormError(event){

        this.error = event.detail;

    }

    

    // handle errors from self

    handleError(error){

        this.error =  error;   

    }

}



//accountinfochild.html


<template>

    <lightning-button variant="brand" label="Click me" title="Click me" onclick={doSomething} class="slds-m-left_x-small"></lightning-button>

</template>



// accountinfochild.js


import { LightningElement } from 'lwc';


export default class Accountinfochild extends LightningElement {

    doSomething() {

        throw new Error('Whoops!');

   }

}


No comments:

Post a Comment