---
schema_version: "1"
id: 26231e45cb1eb3c4fb4fbca3dbdf49b1ff619404117141dd87f9a4219df36d89
title: Create a Custom Pre-Chat Form Using LWC
collection: developer
version: current
locale: en-us
portal_url: https://docs.salesforce.com/developer/current/en-us/service-cloud/messaging-web/guides/create-custom-pre-chat-form.md
canonical_url: https://developer.salesforce.com/docs/service/messaging-web/guide/create-custom-pre-chat-form.html
source_site: developer.salesforce.com
content_type: documentation
content_hash: ce61e7bb0b67a8c62a009cb2e16d8a9a41fbfcc1d54989c0eeb716c512b93a00
products:
  - Enhanced Web Chat
  - Service Cloud Developer Content
---
# Create a Custom Pre-Chat Form Using LWC

**note:** In Spring ’24 and earlier, Enhanced Web Chat doesn't have [Lightning Locker](https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/security_code.htm) turned on, but we recommend you build Lightning Locker compatible code for custom-built Lightning Web Components (LWC).

By using a custom pre-chat component, you can customize the user interface for the pre-chat form. These steps show you how to create a custom pre-chat form using LWC. The pre-chat form we use in the example shows the pre-chat fields configured in **Embedded Service Deployments** in Setup. See [Customize Pre-Chat for Enhanced Chat](https://help.salesforce.com/s/articleView?id=service.miaw_custom_prechat_2.htm).

1. Create an LWC bundle. See [_Salesforce Trailhead_: Build Lightning Web Components](https://trailhead.salesforce.com/content/learn/trails/build-lightning-web-components).

   Let's call our example bundle customPreChatForm.

2. In the customPreChatForm.js-meta.xml configuration file of your LWC, specify the `lightningSnapin__MessagingPreChat` target.

   You add this target to the configuration file so you can see the LWC in your Enhanced Web Chat experience. In other words, adding this target makes the LWC available for selection in **Custom UI Components** in **Embedded Service Deployments** in Setup. See [Customize your UI with Lightning Web Components](https://help.salesforce.com/s/articleView?id=service.messaging_lightning_web_components.htm).

   ```xml
<?xml version="1.0" encoding="UTF-8"?>
   <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
     <apiVersion>59.0</apiVersion>
     <isExposed>true</isExposed>
     <targets>
       <target>lightningSnapin__MessagingPreChat</target>
     </targets>
   </LightningComponentBundle>
```

3. In the customPreChatForm.html file, iterate over the `fields` object to render the pre-chat fields in the UI.

   The `fields` object is configured in the customPreChatForm.js file. This HTML code creates a custom pre-chat component similar to the default one.

   ```html
<template>
       <template class="slds-m-around_medium" for:each={fields} for:item="field">
           <c-custom-pre-chat-form-field key={field.name}
                                       field-info={field}>
           </c-custom-pre-chat-form-field>
       </template>
       <lightning-button label={startConversationLabel}
                       title={startConversationLabel}
                       onclick={onStartConversationClick}
                       class="slds-m-left_x-small"
                       disabled={isSubmitButtonDisabled}>
       </lightning-button>
   </template>
```

4. In the customPreChatForm.js file, specify the `dispatchEvent` function.

   This function takes a `CustomEvent` object with two fields. The first field is the event name `preChatSubmit`, and the second one is a JSON payload with the form field values. The `prechatsubmit` event sends the pre-chat fields configured in **Embedded Service Deployments** in Setup to the chat request.

   ```javascript
import { track, api, LightningElement } from "lwc";

   export default class CustomPreChatForm extends LightningElement {
       /**
       * Deployment configuration data.
       * @type {Object}
       */
       @api configuration = {};

       startConversationLabel;

       isSubmitButtonDisabled = false;

       get prechatForm() {
           const forms = this.configuration.forms || [];
           return forms.find(form => form.formType === "PreChat") || {};
       }

       get prechatFormFields() {
           return this.prechatForm.formFields || [];
       }

       /**
       * Returns pre-chat form fields sorted by their display order.
       * @type {Object[]}
       */
       get fields() {
           let fields =  JSON.parse(JSON.stringify(this.prechatFormFields));
           this.addChoiceListValues(fields);
           return fields.sort((fieldA, fieldB) => fieldA.order - fieldB.order);
       }

       connectedCallback() {
           this.startConversationLabel = "Start Conversation";
       }

       /**
       * Adds values to choiceList (dropdown) fields.
       */
       addChoiceListValues(fields) {
           for (let field of fields) {
               if (field.type === "ChoiceList") {
                   const valueList = this.configuration.choiceListConfig.choiceList.find(list => list.choiceListId === field.choiceListId) || {};
                   field.choiceListValues = valueList.choiceListValues || [];
               }
           }
       }

       /**
       * Iterates over and validates each form field. Returns true if all the fields are valid.
       * @type {boolean}
       */
       isValid() {
           let isFormValid = true;
           this.template.querySelectorAll("c-custom-pre-chat-form-field").forEach(formField => {
               if (!formField.reportValidity()) {
                   isFormValid = false;
               }
           });
           return isFormValid;
       }

       /**
       * Gathers and submits pre-chat data to the app on start-conversation-button click.
       * @type {boolean}
       */
       onStartConversationClick() {
           const prechatData = {};
           if (this.isValid()) {
               this.template.querySelectorAll("c-custom-pre-chat-form-field").forEach(formField => {
                   prechatData[formField.name] = String(formField.value);
               });

               this.isSubmitButtonDisabled = true;

               this.dispatchEvent(new CustomEvent(
                   "prechatsubmit",
                   {
                       detail: { value: prechatData }
                   }
               ));
           }
       }
   }
```

   If you want to use the standard pre-chat fields, here's what the `dispatch` function looks like.

   ```javascript
this.dispatchEvent(
   new CustomEvent("prechatsubmit", {
       detail: {
       value: {
           _firstName: "bob",
           _lastname: "jones",
           _email: "bob.jones@gmail.com",
       },
       },
   }),
   );
```

5. In the customPreChatForm.css file, customize the UI style.

   The UI style in this code is similar to the default experience.

   ```css
:host {
       display: flex;
       flex-direction: column;
       flex: 1 1 auto;
       overflow: hidden;
       background: #FFFFFF;
       padding: 2em;
   }

   lightning-button {
       padding-top: 2em;
       text-align: center;
   }
```

6. Create another LWC bundle called customPreChatFormField to define the fields.
7. In the customPreChatFormField.html file, specify how to render the fields in the UI.

   This example uses the `lightning-combobox` component to render `choiceList` (dropdown) fields and the `lightning-input` component to render other field types.

   ```html
<template>
       <template lwc:if={isTypeChoiceList}>
           <lightning-combobox key={fieldInfo.name}
                               label={fieldInfo.labels.display}
                               options={choiceListOptions}
                               value={choiceListDefaultValue}
                               required={fieldInfo.required}>
           </lightning-combobox>
       </template>
       <template lwc:else>
           <lightning-input key={fieldInfo.name}
                           type={type}
                           label={fieldInfo.labels.display}
                           max-length={fieldInfo.maxLength}
                           required={fieldInfo.required}>
           </lightning-input>
       </template>
   </template>
```

8. In the customPreChatFormField.js file, define the fields, including dropdown fields.

   ```javascript
import { track, api, LightningElement } from "lwc";

   export default class CustomPreChatFormField extends LightningElement {
       choiceListDefaultValue;

       /**
       * Form field data.
       * @type {Object}
       */
       @api fieldInfo = {};

       @api
       get name() {
           return this.fieldInfo.name;
       }

       @api
       get value() {
           const lightningCmp = this.isTypeChoiceList ? this.template.querySelector("lightning-combobox") : this.template.querySelector("lightning-input");
           return this.isTypeCheckbox ? lightningCmp.checked : lightningCmp.value;
       }

       @api
       reportValidity() {
           const lightningCmp = this.isTypeChoiceList ? this.template.querySelector("lightning-combobox") : this.template.querySelector("lightning-input");
           return lightningCmp.reportValidity();
       }

       get type() {
           switch (this.fieldInfo.type) {
               case "Phone":
                   return "tel";
               case "Text":
               case "Email":
               case "Number":
               case "Checkbox":
               case "ChoiceList":
                   return this.fieldInfo.type.toLowerCase();
               default:
                   return "text";
           }
       }

       get isTypeCheckbox() {
           return this.type === "Checkbox".toLowerCase();
       }

       get isTypeChoiceList() {
           return this.type === "ChoiceList".toLowerCase();
       }

       /**
       * Formats choiceList options and sets the default value.
       * @type {Array}
       */
       get choiceListOptions() {
           let choiceListOptions = [];
           const choiceListValues = [...this.fieldInfo.choiceListValues];
           choiceListValues.sort((valueA, valueB) => valueA.order - valueB.order);
           for (const listValue of choiceListValues) {
               if (listValue.isDefaultValue) {
                   this.choiceListDefaultValue = listValue.choiceListValueName;
               }
               choiceListOptions.push({ label: listValue.label, value: listValue.choiceListValueName });
           }
           return choiceListOptions;
       }
   }
```

9. The customPreChatFormField LWC bundle requires a customPreChatFormField.js-meta.xml configuration file but without a target.

   ```xml
<?xml version="1.0" encoding="UTF-8"?>
   <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
     <apiVersion>59.0</apiVersion>
     <isExposed>true</isExposed>
     <targets>
     </targets>
   </LightningComponentBundle>
```

10. Deploy the LWC to your org. See [_Salesforce Developer Guide_: Introducing Lightning Web Components](https://developer.salesforce.com/docs/component-library/documentation/en/lwc).

11. Add the LWC to your Embedded Service Deployment. See [_Salesforce Help_: Customize Your UI with Lightning Web Components](https://help.salesforce.com/s/articleView?id=service.messaging_lightning_web_components.htm).
    To get custom LWC configuration details, see [_Salesforce Developer Guide_: Get Custom Lightning Web Components Configuration Details](https://developer.salesforce.com/docs/service/messaging-web/references/m4w-reference/customComponents.html)
