top of page
Writer's pictureD. Dewangan

Send Translated Email Using LWC


Send Translated Email Using LWC

Have you ever thought of sending translated emails in any other language? If yes, so you are on the right page. Let’s understand and see how we can send emails translated into any other foreign language using LWC. This knowledge is impactful while sending emails to foreign clients. Here is an example of how to implement this in LWC:-


We will develop the following features:

● Send Email.

● Reset input fields on button click.

● Allow users to attach files and links.

● Translate subject and body according to ISO 639-1 Code for language. Ex: fr(French), hi(Hindi).


Here are the steps we will walk through to achieve the above functionalities:

● Subscribe to a translation API.

This will help us get the access key for the translation API.

● Add the named credential to your org.

This will authorize the endpoint in the org, hence making access to the endpoint.

● Create a class: EmailHandler

Here we will write methods to handle the REST API, searches on input email addresses, and translation of Input.

● Create LWC components:

emailInput - This will be the child component for emailLWC that will be handling input validation providing a toast message on invalid input, and reset input on click

emailLWC - This will set the translated text, and provide the functionality to attach files, links, and send emails.


Our output would come up like this:

The subject and body will be translated into the target language when clicking the translate button.


Step 1: Subscribe to a translation API

We will be using the powerful Google Translate API to translate text.

● Subscribe to google Translate API.

● Click on POST translate. The attributes on the right side would be used in translation in EmailHandler class. ( In step 3, you need to replace the ‘X-RapidAPI-key’ with your API key).


Step 2: Add a named credential for the Endpoint.

Create a named credential to specify the URL of a callout endpoint and its required authentication parameters in one definition. To know, how to add a named credential, You may refer to here.



Step 3: Make a class: EmailHandler

public with sharing class EmailHandler {
        
    @AuraEnabled
    public static void   sendEmailController(String emailDetailStr) {
        EmailWrapper emailDetails =   (EmailWrapper)JSON.deserialize(
            emailDetailStr,
            EmailWrapper.class
        );
         Messaging.reserveSingleEmailCapacity(1);
        try {
             messaging.SingleEmailMessage mail = new messaging.SingleEmailMessage();
             mail.setToAddresses(emailDetails.toAddress);
             mail.setCcAddresses(emailDetails.ccAddress);
            mail.setReplyTo(label.EMAIL_REPLY_ADDRESS);
            mail.setSenderDisplayName(label.EMAIL_SENDER_NAME);
             mail.setSubject(emailDetails.subject);
             mail.setHtmlBody(emailDetails.body);
             mail.setEntityAttachments(emailDetails.files);
            Messaging.sendEmail(new List<messaging.SingleEmailMessage>{   mail });
        } catch (exception e)   {
            throw new   AuraHandledException(e.getMessage());
        }
    }

    @AuraEnabled(cacheable = true)
    public static String   languageTranslate(String Text, String sourceLangCode, String targetLangCode) {
        Http http = new http();
        Httprequest req = new httprequest();
        req.setEndpoint(label.TRANSLATIONAPI_ENDPOINT);
        req.setMethod(label.API_METHOD_POST);
        req.setHeader(label.CONTENT_TYPE, label.CONTENT_TYPE_VALUE);
        req.setHeader(label.ACCEPT_ENCODING, label.ACCEPTED_ENCODING_VALUE);
        req.setHeader(label.X_RAPIDAPI_KEY, ‘YOUR_RAPIDAPI_KEY_VALUE’);
        req.setHeader('X-RapidAPI-Host', 'google-translate1.p.rapidapi.com');
        String body = 'q=' + Text + '&target=' +   targetLangCode + '&source=' + sourceLangCode;
        req.setBody(body);
        Httpresponse response =   http.send(req);
        Map<String,Object> data = (Map<String,Object>)((Map<String,Object>)JSON.deserializeUntyped(     
         response.getBody())
     ).get('data');
        object translations =   (object)data.get('translations');
        String ans = JSON.serialize(translations).split(':')[1].substringBetween('"');
        return ans;
    }

    Class EmailWrapper {
        public List<String> toAddress;
        public List<String> ccAddress;
        public String subject;
        public String body;
        public List<String> files;
    }
   }

Step 4: Create LWC component: emailInput

emailInput.html

<template>
    <div class="slds-combobox_container">
        <div class={boxClass}>
            <div class="slds-combobox__form-element   slds-has-focus">
                <template for:each={selectedValues}   for:item="selectedValue" for:index="index">
                    <lightning-pill
                         key={selectedValue}
                         label={selectedValue}
                         onremove={handleRemove}
                        data-index={index}>
                     </lightning-pill>
                </template>
                <input
                    type="text"
                    id="to"
                    class="input"
                    required
                    onkeypress={handleKeyPress}
                     onblur={handleBlur}/>             
            </div>            
            <div
                id="listbox-id-3"
                class="slds-dropdown   slds-dropdown_length-with-icon-7 slds-dropdown_fluid"
                role="listbox"
                if:true={hasItems}>
                <ul class="slds-listbox   slds-listbox_vertical" role="presentation">
                    <template for:each={items} for:item="item" for:index="index">
                        <li
                             key={item.Id}
                             data-id={item.Id}
                             onclick={onSelect}
                            role="presentation"
                            class="slds-listbox__item">
                            <div
                                 aria-selected="true"
                                class=
                                   "slds-media
                                     slds-listbox__option slds-listbox__option_entity"                                
                                role="option"
                                 tabindex="0">
                                 <span class="slds-media__figure slds-listbox__option-icon">
                                     <span class="slds-icon_container   slds-icon-standard-account">
                                         <svg class="slds-icon slds-icon_small" aria-hidden="true">
                                             <use 
                                             xlink:href= SVG_ACCOUNT_LINK>
                                          </use>
                                         </svg>
                                     </span>
                                 </span>
                                <span class="slds-media__body">
                                     <span class="slds-listbox__option-text   slds-listbox__option-text_entity">
                                     {item.Name}</span>
                                     <span class="slds-listbox__option-meta   slds-listbox__option-meta_entity">
                                     {item.Email}</span>
                                 </span>
                             </div>
                        </li>
                    </template>
                </ul>
            </div>
        </div>
    </div>
   </template>

emailInput.js

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

const ENTER_KEY_CODE = 13;
const BLUR_TIMEOUT_VALUE = 300;
const   SVG_ACCOUNT_LINK = "/assets/icons/standard-sprite/svg/symbols.svg#account";

   export default class EmailInput extends LightningElement {
    @track items = [];
    searchTerm = "";
    blurTimeout;
    boxClass = "slds-combobox   slds-dropdown-trigger slds-dropdown-trigger_click slds-has-focus";
    _selectedValues = [];
    selectedValuesMap = new Map();

    get selectedValues() {
        return this._selectedValues;
    }

    set selectedValues(value) {
        this._selectedValues = value;
        const selectedValuesEvent = new CustomEvent(
         "selection", {detail:   {selectedValues: this._selectedValues}
        });
        this.dispatchEvent(selectedValuesEvent);
    }

    get hasItems() {
        return this.items.length;
    }
    
     handleBlur() {
        this.blurTimeout = setTimeout(() => {
            this.boxClass = "slds-combobox   slds-dropdown-trigger slds-dropdown-trigger_click slds-has-focus";
            const value = this.template.querySelector('input.input').value
            if (value !== undefined   && value != null && value !== "") {
                this.selectedValuesMap.set(value, value);
                this.selectedValues   = [...this.selectedValuesMap.keys()];
            }
            this.template.querySelector('input.input').value = "";
        }, BLUR_TIMEOUT_VALUE);
    }

    handleKeyPress(event) {       
        if (event.keyCode === ENTER_KEY_CODE) {
            event.preventDefault();   
            const value = this.template.querySelector('input.input').value;
            if (value !== undefined   && value != null && value !== "") {
                this.selectedValuesMap.set(value, value);
                this.selectedValues   = [...this.selectedValuesMap.keys()];
            }
            this.template.querySelector('input.input').value = "";
        }
    }

    handleRemove(event) {
        const item = event.target.label;
        this.selectedValuesMap.delete(item);
        this.selectedValues = [...this.selectedValuesMap.keys()];
    }

    onSelect(event) {
        this.template.querySelector('input.input').value = "";
        let ele = event.currentTarget;
        let selectedId = ele.dataset.id;
        let selectedValue = this.items.find((record)   => record.Id === selectedId);
        this.selectedValuesMap.set(selectedValue.Email,   selectedValue.Name);
        this.selectedValues = [...this.selectedValuesMap.keys()];
        let key = this.uniqueKey;
        const valueSelectedEvent = new CustomEvent("valueselect", {
            detail: { selectedId, key }
        });
        this.dispatchEvent(valueSelectedEvent);
        if (this.blurTimeout) {
            clearTimeout(this.blurTimeout);
        }
        this.boxClass = "slds-combobox slds-dropdown-trigger   slds-dropdown-trigger_click slds-has-focus";
    }

    @api reset() {
        this.selectedValuesMap = new Map();
        this.selectedValues = [];
    }

    @api validate() {
        this.template.querySelector('input').reportValidity();
        const isValid = this.template.querySelector('input').checkValidity();
        return isValid;
    }
   }

Step 5: Create LWC component: emailLWC

emailLWC.html

<template>
    <article class="slds-card">
        <!-- Alert -->
        <div if:true={noEmailError} class="slds-notify   slds-notify_alert slds-alert_error" role="alert">
            <span   class="slds-assistive-text">{label.ERROR}</span>
            <span
                class="slds-icon_container   slds-icon-utility-error slds-m-right_x-small"
                title="Description   of icon when needed">
                <svg   class="slds-icon   slds-icon_x-small" aria-hidden="true">
                    <use   xlink:href={SVG_ERROR_LINK}></use>
                </svg>
            </span>
            <h2>
                {label.RECEIPENT}
            </h2>
            <div   class="slds-notify__close">
                <button
                    class="slds-button   slds-button_icon slds-button_icon-small slds-button_icon-inverse"
                    title="Close">
                    <svg   class="slds-button__icon" aria-hidden="true">
                        <use   xlink:href={SVG_CLOSE_LINK}></use>
                    </svg>
                    <span   class="slds-assistive-text">{label.CLOSE}</span>
                </button>
            </div>
        </div>
        <div if:true={invalidEmails} class="slds-notify   slds-notify_alert slds-alert_error" role="alert">
            <span   class="slds-assistive-text">{label.ERROR}</span>
            <span
                class="slds-icon_container   slds-icon-utility-error slds-m-right_x-small"
                title="Description   of icon when needed">
                <svg   class="slds-icon   slds-icon_x-small" aria-hidden="true">
                    <use   xlink:href={SVG_ERROR_LINK}></use>
                </svg>
            </span>
            <h2>
                {label.INVALID_EMAIL_MESSAGE}
            </h2>
            <div   class="slds-notify__close">
                <button
                    class="slds-button   slds-button_icon slds-button_icon-small slds-button_icon-inverse"
                    title="Close">
                    <svg   class="slds-button__icon" aria-hidden="true">
                        <use   xlink:href=>{SVG_CLOSE_LINK}</use>
                    </svg>
                    <span   class="slds-assistive-text">{label.CLOSE}</span>
                </button>
            </div>
        </div>
        <div class="slds-card__body   slds-card__body_inner">
            <div   class="slds-form   form slds-var-p-top_small">
                <div   class="slds-form-element   slds-form-element_horizontal slds-form-element_1-col">
                    <label   class="slds-form-element__label" for="to">{label.TO}</label>
                    <div class="slds-form-element__control">
                        <c-email-input   onselection={handleToAddressChange}></c-email-input>
                    </div>
                </div>
                <div   class="slds-form-element   slds-form-element_horizontal slds-form-element_1-col">
                    <label   class="slds-form-element__label" for="cc">{label.CC}</label>
                    <div   class="slds-form-element__control">
                        <c-email-input   onselection={handleCcAddressChange}></c-email-input>
                    </div>
                </div>
                <div   class="slds-form-element">
                    <label   class="slds-form-element__label" for="sourceLangCode">{label.SOURCE_LANGUAGE_CODE}
                    </label>
                    <div   class="slds-form-element__control">
                        <input
                            type="text"
                            name={label.SOURCE_LANGUAGE_CODE}
                            id="sourceLangCode"
                            value={sourceLangCode}
                            class="slds-input"
                            onchange={handleSourceChange}/>
                    </div>
                </div>
                <div   class="slds-form-element">
                    <label   class="slds-form-element__label" for="targetLangCode">{label.TARGET_LANGUAGE_CODE}
                    </label>
                    <div   class="slds-form-element__control">
                        <input
                            type="text"
                            name={label.TARGET_LANGUAGE_CODE}
                            id="targetLangCode"
                            value={targetLangCode}
                            class="slds-input"
                            onchange={handleTargetChange}/>
                    </div>
                </div>
                <div   class="slds-form-element">
                    <label   class="slds-form-element__label" for="subject"> </label>
                    <div   class="slds-form-element__control">
                        <input
                            type="text"
                            name={label.SUBJECT}
                            id="subject"
                            value={subject}
                             placeholder={label.SUBJECT}
                            class="slds-input"
                            onchange={handleSubjectChange}/>
                    </div>
                </div>
                <div   class="slds-form-element">
                    <div   class="slds-form-element__control   slds-var-p-top_small">
                        <lightning-input-rich-text   value={body} onchange={handleBodyChange}>                                         </lightning-input-rich-text>
                    </div>
                </div>
            </div>
        </div>
        <div class="slds-var-p-around_medium">
            <template   for:each={files} for:item="file" for:index="index">
                <lightning-pill
                    key={file.contentVersionId}
                    label={file.name}
                    onremove={handleRemove}
                    data-id={file.contentVersionId}
                    data-index={index}>
                    <lightning-icon
                        icon-name="doctype:attachment"
                        size="xx-small"
                         alternative-text={label.ATTACH_FILES}>
                    </lightning-icon>
                </lightning-pill>
            </template>
        </div>
        <div class="slds-grid   slds-grid_align-end slds-var-p-around_x-small">
            <div   class="slds-col   slds-var-p-right_x-small slds-var-p-bottom_x-small slds-is-relative">
                <section
                    if:true={wantToUploadFile}
                    aria-describedby="dialog-body-id-108"
                    aria-labelledby="dialog-heading-id-3"
                    class="slds-popover   slds-popover_walkthrough slds-nubbin_bottom slds-is-absolute popover"
                    role="dialog">                
                    <button   class=
                           "slds-button   slds-button_icon slds-button_icon-small
                            slds-float_right
                             slds-popover__close
                             slds-button_icon-inverse"
                        title="Close   dialog">
                        <lightning-button-icon
                            variant="bare-inverse"
                            size="small"
                            onclick={toggleFileUpload}
                            icon-name="utility:close"
                             alternative-text="close">
                        </lightning-button-icon>
                        <span   class="slds-assistive-text">{label.CLOSE}</span>
                    </button>
                    <header   class="slds-popover__header   slds-p-vertical_medium">
                      <h2 id="dialog-heading-id-3" class="slds-text-heading_medium">{label.UPLOAD_FILES}                            </h2>
                    </header>
                    <div   class="slds-popover__body" id="dialog-body-id-108">
                        <lightning-file-upload
                            label={label.ATTACH_FILES}
                            name={label.ATTACH_FILES}
                            accept={acceptedFormats}
                            record-id={myRecordId}
                             onuploadfinished={handleUploadFinished}
                             multiple>                         
                        </lightning-file-upload>
                    </div>
                </section>
                <lightning-button-icon
                    icon-name="utility:attach"
                    onclick={toggleFileUpload}
                    alternative-text={label.ATTACH_FILES}
                    title={label.ATTACH_FILES}>
                </lightning-button-icon>
            </div>
            <div   class="slds-col   slds-var-p-right_x-small slds-var-p-bottom_x-small">
                <lightning-button   label={label.RESET} title={label.RESET} onclick={handleReset}></lightning-button>
            </div>
            <div   class="slds-col   slds-var-p-right_x-small slds-var-p-bottom_x-small">
                <lightning-button   label={label.TRANSLATE} title={label.TRANSLATE}   onclick={handleTranslation}>
                </lightning-button>
            </div>
            <div   class="slds-col   slds-var-p-right_x-small slds-var-p-bottom_x-small">
                <lightning-button
                    variant="brand"
                    label={label.SEND}
                    title={label.SEND}
                    onclick={handleSendEmail}>
                </lightning-button>
            </div>
        </div>
    </article>
</template>

emailLWC.js

import { LightningElement, track } from "lwc";
import   sendEmailController from "@salesforce/apex/EmailHandler.sendEmailController";
import   languageTranslate from "@salesforce/apex/EmailHandler.languageTranslate";
import ERROR from "@salesforce/label/c.ERROR";
import CLOSE from "@salesforce/label/c.CLOSE";
import RECEIPENT from   "@salesforce/label/c.RECEIPENT";
import UPLOAD_FILES   from "@salesforce/label/c.UPLOAD_FILES";
import   INVALID_EMAIL_MESSAGE from "@salesforce/label/c.INVALID_EMAIL_MESSAGE";
import ATTACH_FILES from "@salesforce/label/c.ATTACH_FILES";
import TRANSLATE from   "@salesforce/label/c.TRANSLATE";
import EMAIL_SENDER_NAME from "@salesforce/label/c.EMAIL_SENDER_NAME";
import   EMAIL_REPLY_ADDRESS from "@salesforce/label/c.EMAIL_REPLY_ADDRESS";
import SOURCE_LANGUAGE_CODE from "@salesforce/label/c.SOURCE_LANGUAGE_CODE";
import   TARGET_LANGUAGE_CODE from "@salesforce/label/c.TARGET_LANGUAGE_CODE";
import RAPIDAPI_KEY_VALUE from "@salesforce/label/c.RAPIDAPI_KEY_VALUE";
import X_RAPIDAPI_KEY from "@salesforce/label/c.X_RAPIDAPI_KEY";
import ACCEPTED_ENCODING_VALUE from "@salesforce/label/c.ACCEPTED_ENCODING_VALUE";
import ACCEPT_ENCODING from "@salesforce/label/c.ACCEPT_ENCODING";
import CONTENT_TYPE from "@salesforce/label/c.CONTENT_TYPE";
import CONTENT_TYPE_VALUE from "@salesforce/label/c.CONTENT_TYPE_VALUE";
import API_METHOD_POST from "@salesforce/label/c.API_METHOD_POST";
import TRANSLATIONAPI_ENDPOINT from "@salesforce/label/c.TRANSLATIONAPI_ENDPOOINT";
import SEND from "@salesforce/label/c.SEND";
import RESET from "@salesforce/label/c.RESET";
import TO from "@salesforce/label/c.TO";
import CC from "@salesforce/label/c.CC";


const SVG_ERROR_LINK = "/assets/icons/utility-sprite/svg/symbols.svg#error";
const SVG_CLOSE_LINK = "/assets/icons/utility-sprite/svg/symbols.svg#close";
   export default class EmailLWC extends LightningElement {
    toAddress = [];
    ccAddress = [];
    @track files = [];
    sourceLangCode = "";
    targetLangCode = "";
    subject = "";
    body = "";
         error;
    wantToUploadFile = false;
    noError = false;
    invalidEmails = false;
         label = {ERROR, CLOSE, RECEIPENT,   UPLOAD_FILES, INVALID_EMAIL_MESSAGE, TO, CC};

    toggleFileUpload() {
        this.wantToUploadFile = !this.wantToUploadFile;
    }

    handleUploadFinished(event) {
        const uploadedFiles =   event.detail.files;
        this.files = [...this.files, ...uploadedFiles];
        this.wantToUploadFile = false;
    }

    handleRemove(event) {
        const index =   event.target.dataset.index;
        this.files.splice(index, 1);
    }

    handleToAddressChange(event) {
        this.toAddress = event.detail.selectedValues;
    }

    handleCcAddressChange(event) {
        this.ccAddress = event.detail.selectedValues;
    }

    handleSourceChange(event) {
        this.sourceLangCode = event.target.value;
    }

    handleTargetChange(event) {
        this.targetLangCode = event.target.value;
    }

    handleSubjectChange(event) {
        this.subject = event.target.value;
    }

    handleBodyChange(event) {
        this.body = event.target.value;
    }

    handleTranslation() {
        languageTranslate({
            Text: this.subject,
            sourceLangCode: this.sourceLangCode,
            targetLangCode: this.targetLangCode
        })
        .then(result => {
            this.subject =   result;
        })
        .catch((error) =>   {
            this.error = error;
        });
         languageTranslate({
            Text: this.body,
            sourceLangCode: this.sourceLangCode,
            targetLangCode: this.targetLangCode
        })
        .then(result => {
            this.body = result;
        })
        .catch((error) =>   {
            this.error = error;
        });
    }

    validateEmails(emailAddressList) {
        let areEmailsValid;
        if(emailAddressList.length > 1) {
            areEmailsValid =   emailAddressList.reduce((accumulator, next) => {
                const isValid = this.validateEmail(next);
                return accumulator && isValid;
            });
        }
        else if(emailAddressList.length > 0) {
            areEmailsValid = this.validateEmail(emailAddressList[0]);
        }
        return areEmailsValid;
    }

    validateEmail(email) {
        const res = 
         /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()s[\]\\.,;:\s@"]+)*)|
         (".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|
            (([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
        return res.test(String(email).toLowerCase());
    }

    handleReset() {
        this.toAddress = [];
        this.ccAddress = [];
        this.subject = "";
        this.body = "";
        this.files = [];
         this.sourceLangCode   = "";
         this.targetLangCode   = "";
         this.template.querySelectorAll("c-email-input").forEach((input)   => input.reset());
    }

    handleSendEmail() {
        this.noError = false;
        this.invalidEmails = false;
        if (![...this.toAddress, ...this.ccAddress].length   > 0) {
            this.noError = true;
            return;
        }
        if (!this.validateEmails([...this.toAddress, ...this.ccAddress])) {
            this.invalidEmails   = true;
            return;
        }

        let emailDetails = {
            toAddress: this.toAddress,
            ccAddress: this.ccAddress,
            subject: this.subject,
            body: this.body
        };
        
         sendEmailController({emailDetailStr: JSON.stringify(emailDetails)})
            .then(() => {
         })
            .catch((error) =>   {
                this.error = error;
            });
    }
   }

emailLWC.js-meta.xml

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle   xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>55.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__HomePage</target>
        <target>lightning__RecordPage</target>
    </targets>
</LightningComponentBundle>

CUSTOM LABELS USED:

{label.TO}

To

{label.CC}

Cc

{label.CLOSE}

Close

{label.ERROR}

Error

{label.SUBJECT}

Subject

{label.RECEIPENT}

Please add a receipent

{label.ATTACH_FILES}

Attach files

{label.TRANSLATE}

Translate

{label.UPLOAD_FILES}

Upload Files

{label.INVALID_EMAIL_MESSAGE}

Some of the emails are invalid

{label.SOURCE_LANGUAGE_CODE}

Source Language Code

{label.TARGET_LANGUAGE_CODE}

Target Language Code

{label.EMAIL_REPLY_ADDRESS}

team.avenoir@gmail.com

{label.EMAIL_SENDER_NAME}

Avenoir Innovations Pvt Ltd.

{label.TRANSLATIONAPI_ENDPOINT}

https://google-translate1.p.rapidapi.com/language/translate/v2

{label.API_METHOD_POST}

POST

{label.CONTENT_TYPE}

content-type

{label.CONTENT_TYPE_VALUE}

application/x-www-form-urlencoded

{label.ACCEPT_ENCODING}

Accept-Encoding

{label.ACCEPTED_ENCODING_VALUE}

application/gzip

{label.X_RAPIDAPI_KEY}

X-RapidAPI-Key

{label.RAPIDAPI_KEY_VALUE}

your API key

{label.SEND}

Send

{label.RESET}

Reset

Conclusion

In conclusion, this tutorial provides a comprehensive guide on how to create a Lightning Web Component (LWC) for sending translated emails in foreign languages. It outlines a step-by-step process for implementing this feature, including setting up a translation API, creating a named credential, developing an LWC component, and handling email-sending functionality. The LWC allows users to input email recipients, subject, and body, translate the content into the target language, attach files, and send emails. This solution is particularly valuable for communicating with foreign clients. By following this guide, you can enhance your Salesforce org's email capabilities, making it more accessible and efficient for global communication.


If you'd like to see the code and resources used in this project, you can access the repository on GitHub.To access the AVENOIRBLOGS repository, click here. Feel free to explore the code and use it as a reference for your own projects.


Happy Coding!! To help you add to your knowledge. You can leave a comment to help me understand how the blog helped you. If you need further assistance, please leave a comment or contact us at Reach us. You can click on "Reach Us" on the website and share the issue with me.


REFERENCES:




Blog Credit:

D. Dewangan

Salesforce Developer

Avenoir Technologies Pvt. Ltd.



Reach us: team@avenoir.ai

Recent Posts

See All

Comentarios


bottom of page