Hey! I am having this issue. I have added the script to the Custom JS and my name and email fields are not being required on the AI Chat Bot form. Thanks!
Welcome to the Community, @Roben-Marie_Smith ![]()
I’ve forwarded your request to the devs and they’ll check the script. I’ll keep you updated ![]()
Hi there, @Roben-Marie_Smith ![]()
The previous script works only if of all form fields are used in the widget. Your widget doesn’t have a Phone field, so we’ve adjusted the script for you:
(function() {
const WIDGET_WINDOW_SELECTOR = '.es-window-container';
const FORM_SELECTOR = 'form';
const SUBMIT_BTN_SELECTOR = 'button[type="submit"]';
const REQUIRED_FIELDS = ['name', 'email', 'phone'];
const FIELD_CONTAINER_SELECTOR = '[class*="FormFieldLayout__Element"]';
const PLACEHOLDER_SELECTOR = '[class*="TextControlBase__TextControlBasePlaceholder"]';
const ERROR_MSG_CLASS = 'es-custom-error-message';
const EMPTY_ERROR_TEXT = 'This field is required';
const createErrorElement = (text) => {
const el = document.createElement('div');
Object.assign(el.style, {
color: 'rgb(255, 56, 56)',
fontSize: '12px',
lineHeight: '14px',
marginTop: '4px',
});
el.className = ERROR_MSG_CLASS;
el.innerText = text;
return el;
};
const getContainer = (input) => input.closest(FIELD_CONTAINER_SELECTOR) || input.parentNode;
const showInputError = (input) => {
const container = getContainer(input);
if (!container) return;
if (!container.querySelector(`.${ERROR_MSG_CLASS}`)) {
container.appendChild(createErrorElement(EMPTY_ERROR_TEXT));
}
input.style.borderColor = 'rgb(255, 56, 56)';
};
const hideInputError = (input) => {
const container = getContainer(input);
if (!container) return;
const errorEl = container.querySelector(`.${ERROR_MSG_CLASS}`);
if (errorEl) errorEl.remove();
input.style.borderColor = '';
};
const addAsteriskToPlaceholder = (input) => {
const container = getContainer(input);
const placeholder = container?.querySelector(PLACEHOLDER_SELECTOR);
if (placeholder && !placeholder.textContent.includes('*')) {
placeholder.textContent = `${placeholder.textContent.trim()} *`;
}
};
const processForm = (form) => {
if (form.dataset.isValidatorAttached === 'true') return;
form.dataset.isValidatorAttached = 'true';
const submitBtn = form.querySelector(SUBMIT_BTN_SELECTOR);
if (!submitBtn) return;
const activeInputs = [];
REQUIRED_FIELDS.forEach(fieldName => {
const input = form.querySelector(`input[name="${fieldName}"]`);
if (input) {
activeInputs.push(input);
addAsteriskToPlaceholder(input);
input.addEventListener('input', () => hideInputError(input));
}
});
if (activeInputs.length === 0) return;
submitBtn.addEventListener('click', (e) => {
let hasError = false;
activeInputs.forEach(input => {
const val = input.value.trim();
if (!val) {
showInputError(input);
hasError = true;
}
});
if (hasError) {
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
}
}, true);
};
const watchWidgetContent = (widgetNode) => {
const existingForm = widgetNode.querySelector(FORM_SELECTOR);
if (existingForm) processForm(existingForm);
const widgetObserver = new MutationObserver((mutations) => {
for (const mutation of mutations) {
if (mutation.addedNodes.length) {
mutation.addedNodes.forEach(node => {
if (node.nodeType !== 1) return;
if (node.matches(FORM_SELECTOR)) {
processForm(node);
} else {
const nestedForm = node.querySelector(FORM_SELECTOR);
if (nestedForm) processForm(nestedForm);
}
});
}
}
});
widgetObserver.observe(widgetNode, {
childList: true,
subtree: true
});
};
const globalObserver = new MutationObserver((mutations) => {
for (const mutation of mutations) {
if (mutation.addedNodes.length) {
mutation.addedNodes.forEach(node => {
if (node.nodeType !== 1) return;
if (node.matches(WIDGET_WINDOW_SELECTOR)) {
watchWidgetContent(node);
} else if (node.querySelector(WIDGET_WINDOW_SELECTOR)) {
watchWidgetContent(node.querySelector(WIDGET_WINDOW_SELECTOR));
}
});
}
}
});
const existingWidget = document.querySelector(WIDGET_WINDOW_SELECTOR);
if (existingWidget) {
watchWidgetContent(existingWidget);
}
globalObserver.observe(document.body, {
childList: true,
subtree: true
});
})();
Please try it out and let me know if it’s working fine on your end now ![]()
