Custom Pre-Chat Form in Einstein Bots using LWC

Custom pre-chat form is required when you want to do away with the standard pre-chat in Einstein Bot. Custom pre-chat form enables you to have more control on field validations at client side level and if you want to add more security against DDoS(Distributed Denial of Service) and/or Attach Vectors by implementing Google reCAPTCHA. Click here to know on how to customize the pre-chat form.


By the end of this blog, you will be able to:

  1. Create Custom pre-chat form with all validations on client side.
  2. Host the custom pre-chat form in Einstein Bot.

Components:

  1. Create Static Resource botPreChatFormCSS: First step is to create a static resource. We will use this static resource to left align the error message on our pre-chat form.
    botPreChatFormCSS.css
    .text-align .slds-form-element__help {
        text-align: left;
    }
    botPreChatFormCSS.resource-meta.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <StaticResource xmlns="http://soap.sforce.com/2006/04/metadata">
        <cacheControl>Public</cacheControl>
        <contentType>text/css</contentType>
    </StaticResource>
  2. Create LWC botPreChatForm: Next is to create a lightning web component botPreChatForm which will import the lightningsnapin/basePrechat
    botPreChatForm.html
    <template>
        <div if:true={hasFields}>
            <div class="formContent embeddedServiceSidebarForm">
                <div class="slds-var-p-around_medium">
                    <template for:each={fields} for:item="field">
                        <div key={field.name} class="slds-var-p-bottom_small">
                            <span class="slds-form-element__label slds-no-flex slds-float_left">
                                <span if:true={field.required}
                                    class="slds-text-color_destructive slds-var-p-right_xxx-small">*</span>
                                {field.label}
                            </span>
                            <lightning-input name={field.name} type={field.type} label={field.label} variant="label-hidden"
                                class="text-align" value={field.value} required={field.required}>
                            </lightning-input>
                        </div>
                    </template>
                </div>
            </div>
            <div class="buttonWrapper embeddedServiceSidebarForm">
                <button type="button" onclick={handleStartChat}
                    class="slds-button slds-button--neutral startButton uiButton--default uiButton embeddedServiceSidebarButton">
                    <span class="label bBody">{startChatLabel}</span>
                </button>
            </div>
        </div>
    </template>
    botPreChatForm.js
    import BasePrechat from 'lightningsnapin/basePrechat';
    import { api, track } from 'lwc';
    import startChatLabel from '@salesforce/label/c.StartChat';
    import botPreChatFormCSS from "@salesforce/resourceUrl/botPreChatFormCSS";
    import { loadStyle } from "lightning/platformResourceLoader";
    
    export default class BotPreChatForm extends BasePrechat {
        @api prechatFields;
        @track fields;
        @track namelist;
        startChatLabel;
    
        //Set the button label and prepare the prechat fields to be shown in the form.
        connectedCallback() {
            this.startChatLabel = startChatLabel;
            
            if (this.prechatFields) {
                this.fields = this.prechatFields.map(field => {
                    field = JSON.parse(JSON.stringify(field));
                    field.type = field.type.replace('input', '');
                    const { label, name, value, required, maxLength, type } = field;
                    return { label, name, value, required, maxLength, type };
                });
                this.namelist = this.fields.map(field => field.name);
            }
        }
    
        //Focus on the first input after this component renders.
        renderedCallback() {
            Promise.all([
                loadStyle(this, botPreChatFormCSS),
            ]).then(() => { });
            if(!this.inputFocused) {
                let lightningInputElement = this.template.querySelector("lightning-input");
                if (lightningInputElement) {
                    lightningInputElement.focus();
                    this.inputFocused = true;
                };
            }
        }
        
        // getter property to render the prechat fields
        get hasFields() {
            return this.fields && this.fields.length > 0;
        }
    
        //On clicking the 'Start Chatting' button, send a chat request.
        handleStartChat(event) {
            event.preventDefault();
            let inputElements = this.template.querySelectorAll("lightning-input");
            if (inputElements && this.checkInputValidity(inputElements)) {
                inputElements.forEach(input => {
                    this.fields[this.namelist.indexOf(input.name)].value = input.value;
                });
                if (this.validateFields(this.fields).valid) {
                    this.startChat(this.fields);
                } else {
                    // Error handling if fields do not pass validation.
                }
            }
        }
    
        checkInputValidity(inputElements) {
            const allValid = [...inputElements].reduce(
                (validSoFar, inputCmp) => {
                    inputCmp.reportValidity();
                    return validSoFar && inputCmp.checkValidity();
                }, true);
            return allValid;
        }
    }
    botPreChatForm.css
    :host {
        display: flex;
        flex-direction: column;
    }
    
    lightning-button {
        padding-top: 1em;
    }
    
    .embeddedServiceSidebarForm.formContent {
        width: 100%;
        height: 350px;
        overflow-y: auto;
        position: relative;
        background-color: var(--lwc-esColorBackgroundInverse,#fff);
        border-radius: 0 0 8px 8px;
    }
    
    .embeddedServiceSidebarForm.buttonWrapper {
        text-align: center;
        padding: 30px 24px 24px;
        margin: 0;
        width: 100%;
        position: absolute;
        box-sizing: border-box;
        bottom: 0;
        background: linear-gradient(to bottom, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) calc(100% - 77px), rgba(255, 255, 255, 1) 100%);
    }
    
    .embeddedServiceSidebarButton {
        position: relative;
        border: none;
        background: var(--lwc-colorBrand,#2574A9);
        text-shadow: none;
        box-shadow: none;
        border-radius: 4px;
        transition: background .4s ease;
        color: var(--lwc-colorTextInverse,#FFFFFF);
        font-size: var(--lwc-esFontSizeMedium,1em);
        font-weight: var(--lwc-fontWeightRegular,400);
        font-family: var(--lwc-fontFamily,Lato),sans-serif;
        width: 100%;
        margin: 0;
        height: 44px;
    }
    botPreChatForm.js-meta.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
        <apiVersion>52.0</apiVersion>
        <isExposed>true</isExposed>
        <targets>
            <target>lightningSnapin__PreChat</target>
        </targets>
    </LightningComponentBundle>
  3. Override Standard Pre-Chat Form: Now as we have created the custom pre-chat form, it is time to embed this into the Einstein Bot and replace the standard pre-chat form. Follow the below steps:
    • Go to set up → Embedded Service Deployment and click on the click on View in the dropdown menu next to your Service Deployment set up(Test Bot).

    • Click on Edit next to Chat Setting

    • Make sure you have activated the Pre-Chat Page which caters for standard Pre-Chat form

    • Scroll down to bottom and click on Edit next to Customize with Lightning Components and update the Pre-Chat dropdown with the above created LWC botPreChatForm

Note: The Pre-Chat page fields will actually be passed to our custom lightning web component botPreChatForm via lightningsnapin/basePrechat. Having said that, if you make dynamic changes to Pre-Chat fields, they will reflect in our custom LWC also without having to write additional code. This may take couple of minutes to reflect so be patient once you make any such changes. Also making any field required in Pre-Chat page will have same impact in our custom page as well.

Demo:

Now as we have created our custom lightning web component to implement the custom pre-chat form and embedded this into our Bot application, it's time to actually look at the demo of how it looks when we start any chat.


YouTube:


References:

  1. Salesforce LWC lightningsnapin documentation
  2. Custom Pre-chat form sample using Aura

If you like this blog content and find inciteful, please comment and let me know. 

    Comments

    Post a Comment