Стандартная форма обратной связи
Прежде, чем приступать, рекомендую выключить упрощенный режим редактирования форм в настройках модуля Вебформы. И сохранить настройку, в противном случае, бывают баги:
Теперь идем в Сервисы -> Веб формы -> Настройка форм
и жмем там кнопку Создать
, чтобы создать форму:
Во вкладке Свойства
заполняем все необходимые поля. Во вкладке Доступ
проверьте, чтобы для группы Все пользователи
было право Заполнение формы
:
Переходим во вкладку Вопросы
и добавляем поля формы которые увидят пользователи, тут все интуитивно понятно:
Настройка полей для формы:
-
Имя
-
Вкладка Свойства
- Активность:
да
- Символьный идентификатор:
NAME
- Обязателен:
да
- Активность:
-
Вкладка Вопрос
- Заголовок:
Ваше имя
- Заголовок:
-
Вкладка Ответ
- Текст [ANSWER_TEXT]:
ставим пробел
- Значение [ANSWER_VALUE]:
оставляем пустым
- Тип поля:
text
- Параметры:
пусто
- Текст [ANSWER_TEXT]:
-
Вкладка Свойства
-
Телефон
-
Вкладка Свойства
- Активность:
да
- Символьный идентификатор:
TELEFON
- Обязателен:
да
- Активность:
-
Вкладка Вопрос
- Заголовок:
Номер телефона
- Заголовок:
-
Вкладка Ответ
- Текст [ANSWER_TEXT]:
ставим пробел
- Значение [ANSWER_VALUE]:
оставляем пустым
- Тип поля:
text
- Параметры:
phone
- Текст [ANSWER_TEXT]:
-
Вкладка Свойства
Создаем статус по умолчанию для результатов, если он не создался. Во вкладке Доступ
для всех операций поставьте Создатель результата
:
Параметры формы
вкладка с основными настройками формыРезультат
результат заполнения форм пользователямиВопросы
поля которые увидят пользователи в формеПоля
дополнительные поля которые будут отображаться в админке сайта и при выгрузки результатов в exelСтатусы
нужны для реализации сложной схемы работы с веб-формами, когда нужно не просто получить ответы на вопросы от посетителей сайта, но и обработать их: занести в CRM, составить списки по выборочным данным и так далее
Вывод формы
Если вы хотите разместить форму на отдельной странице, создайте страницу для формы. Если хотите разместить в шаблоне, например в шапке, тогда создайте временную страницу, чтобы настраивать форму там. После скопируете вызов компонента формы с временной страницы.
Открываем редактирование страницы в визуальном редакторе, в компонентах ищем form.result.new
, перетягиваем в окно правки:
Через несколько секунд появится окно настройки компонента, нам надо заполнить поля:
ID веб-формы
выбрать нашу формуИспользовать расширенный вывод сообщений об ошибках
даВключить поддержку ЧПУ
нетСтраница со списком результатов
пустоСтраница редактирования результата
пустоСтраница с сообщением об успешной отправке
пусто
После сохранения компонента, на странице появится форма. Она не очень красивая, поэтому установим свой шаблон. Включим режим правки, наведем курсор на форму, там скопируем шаблон, как показано на картинке:
Укажем новое название шаблона, шаблон сайта выберим текущий:
В шаблоне компонента сразу удалим все лишние файлы. Если их не удалить, в будущем они будут создавать путаницу при доработке шаблона, потому что будем иметь полно файлов не понятного назначения. А еще сайт будет тяжелый, так как пользователь будет получать много не нужных скриптов и стилей.
Редактирование шаблона
В template.php
доступны следующие переменные.
Служебные
$arResult["isFormErrors"]
равенY
, если есть ошибки с формой$arResult["isFormNote"]
равенY
, если форма успешно отправлена. С условием по этой переменной можно выводить сообщение об успешной отправке уже без формы$arResult["FORM_HEADER"]
открытие формы и системные теги$arResult["FORM_FOOTER"]
закрытие формы и системные теги$arResult["QUESTIONS"]
массив вопросов формы$arResult["isUseCaptcha"]
равноtrue
, если включен показ капчи$arResult["CAPTCHA_IMAGE"]
тег img с картинкой капчи$arResult["CAPTCHA_FIELD"]
поле для ввода капчи$arResult["F_RIGHT"]
код права на доступ к текущей форме (вкладка Доступ формы)$arResult["WEB_FORM_NAME"]
символьный код формы$arResult["arrVALUES"]
значения полей введенные пользователем$arResult["CAPTCHACode"]
уникальный код капчи. Требуется для вывода картинки$arResult["arForm"]["STAT_EVENT1"]
event1 с вкладки Статистика формы$arResult["arForm"]["STAT_EVENT2"]
event2 с вкладки Статистика формы$arResult["arForm"]["STAT_EVENT3"]
event3 с вкладки Статистика формы
Информация пользователю
$arResult["FORM_ERRORS_TEXT"]
текст ошибок$arResult["FORM_NOTE"]
сообщение об успешной отправке$arResult["FORM_TITLE"]
заголовок формы$arResult["FORM_DESCRIPTION"]
описание формы$arResult["arForm"]["BUTTON"]
текст кнопки Отправить$arResult["REQUIRED_SIGN"]
красная звездочка для подсвечивания обязательных полей
Структура вопроса
Для вывода полей надо брать вопросы из $arResult["QUESTIONS"]
по символьному коду:
CAPTION
имя поляIS_HTML_CAPTION
имя поля в формате HTML, Y/N.REQUIRED
обязательно к заполнению, Y/N.IS_INPUT_CAPTION_IMAGE
есть ли изображение вопросаHTML_CODE
HTML код поляSTRUCTURE
детальное описание поляIMAGE
описание изображения вопроса, если IS_INPUT_CAPTION_IMAGE равен Y.
Например, чтобы вывести инпут поля с символьным кодом NAME
надо сделать в шаблоне так:
<?=$arResult["QUESTIONS"]['NAME']['HTML_CODE']?>
На основе переменных выше соберем шаблон:
template.php<? if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die(); ?>
<? if ($arResult["isFormNote"] === "Y"): ?>
Спасибо, ваша заявка принята!
<? else: ?>
<?= $arResult["FORM_HEADER"] ?>
<input type="hidden" name="web_form_submit" value="Y">
<? if ($arResult["isFormErrors"] === "Y"): ?>
<div class="errors">
<?=$arResult["FORM_ERRORS_TEXT"]?>
</div>
<? endif; ?>
<?= $arResult["QUESTIONS"]['NAME']['CAPTION']?>
<?= ($arResult["QUESTIONS"]['NAME']['REQUIRED'] === 'Y' ? ' *' : '')?>:
<?= $arResult["QUESTIONS"]['NAME']['HTML_CODE']?>
<br>
<?=$arResult["QUESTIONS"]['TELEFON']['CAPTION']?>
<?=($arResult["QUESTIONS"]['TELEFON']['REQUIRED'] === 'Y' ? ' *' : '')?>:
<?=$arResult["QUESTIONS"]['TELEFON']['HTML_CODE']?>
<br>
<input type="submit" value="<?=$arResult["arForm"]["BUTTON"]?>">
<?=$arResult["FORM_FOOTER"]?>
<? endif; ?>
Логика его такая:
Вначале проверяем, подключает ли файл Битрикс или его открыл пользователь введя в браузере адрес шаблона. Если не битрикс — блокируем генерацию шаблона.
Если форма успешно отправлена, выводить сообщение, иначе выводим форму.
Код выводит открытие формы со служебными скрытыми полями:
<?=$arResult["FORM_HEADER"]?>
Поле web_form_submit
в значении Y
триггер для Битрикс, говорящее о том, что форма отправлена и надо проверить, что там ввел пользователь.
Если есть ошибки — выводим их в диве с классом errors
.
Перед закрытием формы, кнопка отправить с тексом, который указан в настройках формы.
Ajax отправка
Этот способ стоит использовать когда есть реальная польза от файла ajax.php
, минусов в этом много, самый главный минус, обработка формы полностью ложится на разработчика и JS. Модернизируем наш шаблон для Ajax:
template.php<?php if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) {
die();
} ?>
<?= $arResult["FORM_HEADER"] ?>
<div class="error-msg"></div>
<div class="success-msg"></div>
<input type="hidden" name="web_form_submit" value="Y">
<?= $arResult["QUESTIONS"]['NAME']['CAPTION']?>
<?= ($arResult["QUESTIONS"]['NAME']['REQUIRED'] === 'Y' ? ' *' : '')?>:
<?= $arResult["QUESTIONS"]['NAME']['HTML_CODE']?>
<br>
<?=$arResult["QUESTIONS"]['TELEFON']['CAPTION']?>
<?=($arResult["QUESTIONS"]['TELEFON']['REQUIRED'] === 'Y' ? ' *' : '')?>:
<?=$arResult["QUESTIONS"]['TELEFON']['HTML_CODE']?>
<br>
<input type="submit" value="<?=$arResult["arForm"]["BUTTON"]?>">
<?= $arResult["FORM_FOOTER"]?>
<script>
ajaxForm(document.getElementsByName('<?=$arResult['arForm']['SID']?>')[0], '<?=$templateFolder?>/ajax.php')
</script>
Создайте в папке шаблона компонента файл script.js
. Этот скрипт обрабатывает отправку формы, которая передается первым параметром, отправляя все данные из нее на ссылку, переданную вторым параметром:
script.jsfunction ajaxForm(obForm, link) {
// устанавливаем функцию обработчик
BX.bind(obForm, 'submit', BX.proxy(function(e) {
// отменяем стандартное действие формы
BX.PreventDefault(e);
// очищаем вывод информации
obForm.getElementsByClassName('error-msg')[0].innerHTML = '';
obForm.getElementsByClassName('success-msg')[0].innerHTML = '';
// запрос
BX.ajax({
url: link,
data: new FormData(obForm),
method: 'POST',
preparePost: false,
onsuccess: function(data){
console.log(JSON.parse(data))
},
onfailure: function(){}
});
}, obForm, link));
}
Создаем в папке шаблона компонента, файл обработчик Ajax запросов:
ajax.php<?php
require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");
// подключаем модуль веб-форм
CModule::IncludeModule("form");
// проверка валидности отправки формы
if (check_bitrix_sessid()) {
// метод проверяет введенные значения на обязательность
$formErrors = CForm::Check($_POST['WEB_FORM_ID'], $_REQUEST, false, "Y", 'Y');
// если не все обязательные поля заполнены
if (count($formErrors)) {
echo json_encode(['success' => false, 'info' => $formErrors]);
}
// в случае успеха, возвращаем ID нового результата, в противном случае false
elseif ($RESULT_ID = CFormResult::Add($_POST['WEB_FORM_ID'], $_REQUEST)) {
// отправляем все события как в компоненте веб форм
// CFormCRM::onResultAdded($_POST['WEB_FORM_ID'], $RESULT_ID);
// CFormResult::SetEvent($RESULT_ID);
// CFormResult::Mail($RESULT_ID);
// говорим что успешно заявку получили
echo json_encode(['success' => true, 'info' => "Сообщение успешно отправленно"]);
} else {
// если возникли ошибки
echo json_encode(['success' => false, 'info' => $GLOBALS["strError"]]);
}
} else {
// предотвращаем CSRF атаку
echo json_encode(['success' => false, 'info' => ['sessid' => 'Не верная сессия. Попробуйте обновить страницу']]);
}
// файл ниже подключать обязательно, там закрытие соединения с базой данных
require_once($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/epilog_after.php');
Ajax отправка битрикс
Чтобы форма отправлялась без перезагрузки страницы, надо добавить в параметры вызова компонента следующее. С помощью этих параметров добавить Ajax можно в любой компонент. Эти параметры — не особенность вебформ, реализована работа с Ajax в базовом классе компонентов. Теперь Битрикс сам добавит нужные скрипты:
"AJAX_MODE" => "Y",
"AJAX_OPTION_SHADOW" => "N",
"AJAX_OPTION_JUMP" => "N",
"AJAX_OPTION_STYLE" => "Y",
"AJAX_OPTION_HISTORY" => "N",
template.php<? if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die(); ?>
<? if ($arResult["isFormNote"] === "Y"): ?>
Спасибо, ваша заявка принята!
<? else: ?>
<?= $arResult["FORM_HEADER"] ?>
<input type="hidden" name="web_form_submit" value="Y">
<? if ($arResult["isFormErrors"] === "Y"): ?>
<div class="errors">
<?=$arResult["FORM_ERRORS_TEXT"]?>
</div>
<? endif; ?>
<?= $arResult["QUESTIONS"]['NAME']['CAPTION']?>
<?= ($arResult["QUESTIONS"]['NAME']['REQUIRED'] === 'Y' ? ' *' : '')?>:
<?= $arResult["QUESTIONS"]['NAME']['HTML_CODE']?>
<br>
<?=$arResult["QUESTIONS"]['TELEFON']['CAPTION']?>
<?=($arResult["QUESTIONS"]['TELEFON']['REQUIRED'] === 'Y' ? ' *' : '')?>:
<?=$arResult["QUESTIONS"]['TELEFON']['HTML_CODE']?>
<br>
<input type="submit" value="<?=$arResult["arForm"]["BUTTON"]?>">
<?=$arResult["FORM_FOOTER"]?>
<? endif; ?>
Алгоритм работы Ajax формы:
- Весь шаблон формы оборачивается в тег с уникальным ID
- После этого тега добавляется JS, который устанавливает событие на отправку формы
- Пользователь отправляет форму
- На сервер запрос через весь шаблон доходит до вызова компонента
- Битрикс обрабатывает введенные данные
- Получает вывод шаблона формы и заменяет на странице в теге, добавленном в пункте 1, всё содержимое
- Результат: страница не перезагружалась, пользователь видит вместо формы сообщение об успешной отправке или ту же форму с ошибками
Из этой логики мы получаем некоторые нюансы. Поля формы, обработанные на джаваскрипте при загрузке страницы, снова будут не обработанные, так как они заменились, а события загрузки страницы заново не было.
Ajax отправка формы на саму себя
Этот способ очень удобен, мы дергаем шаблон компонента через Ajax, компонент обрабатывает логику и отдает валидированную готовую форму, нет необходимости обрабатывать ответ на JS, все обрабатывается на PHP
template.php<?php if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) {
die();
}
use \Bitrix\Main\Application;
$context = Application::getInstance()->getContext();
$request = $context->getRequest();
?>
<div class="form">
<? // проверяем ответ, addok признак успешно отправленной формы ?>
<? $isAjaxSuccess = ($_REQUEST['formresult'] === 'addok'); ?>
<? // если форма успешно отправлена ?>
<?php if ($isAjaxSuccess) : ?>
<? // начинаем буферизацию ?>
<?php $APPLICATION->RestartBuffer(); ?>
<div class="form__success">
<h3>Спасибо за регистрацию!</h3>
<p>Больше полезной информации для предпринимателей в телеграм-канале МоегоСклада</p>
<a class="btn" href="#">Подписаться</a>
</div>
<?php
// убиваем скрипт
if ($isAjaxSuccess) {
die();
}
?>
<?php endif; ?>
<?php
// проверяим данные добавленные в FormData при Ajax запросе
$isAjax = ($request->get('ajax') == 'Y' && $request->get('ajax-type') == $arResult['arForm']['SID']);
// если шаблон дергается через Ajax
if ($isAjax) {
// начинаем буферизацию
$APPLICATION->RestartBuffer();
}
?>
<? // подменяем как нам нужно начало формы ?>
<?= str_replace('<form ', '<form class="form__form" ', $arResult["FORM_HEADER"]) ?>
<? // если есть ощибки, обрабатываем ?>
<?php if (!empty($arResult['FORM_ERRORS'])) : ?>
<? // выводим предупреждения ?>
<?php foreach ($arResult['FORM_ERRORS'] as $errorKey => $errorValue) : ?>
<div class="form__danger">
<?= $errorValue; ?>
</div>
<?php endforeach ?>
<?php endif; ?>
<? // формируем тело формы ?>
<?php foreach ($arResult["QUESTIONS"] as $elementKey => $elementValue) : ?>
<? // если поле скрытое ?>
<?php if ($elementValue['STRUCTURE'][0]['FIELD_TYPE'] === 'hidden') : ?>
<? // получаем данные для формирования поля ?>
<?php $arField = reset($elementValue['STRUCTURE']); ?>
<? // формируем инпут ?>
<input type="hidden" name="form_hidden_<?= $arField['ID'] ?>" value="<?= $arField['VALUE']; ?>">
<?php endif; ?>
<? // если поле не скрытое ?>
<?php if ($elementValue['STRUCTURE'][0]['FIELD_TYPE'] != 'hidden') : ?>
<?php
// получаем данные для формирования поля
$arField = reset($elementValue['STRUCTURE']);
// формируем название поля
$sFieldName = 'form_' . $arField['FIELD_TYPE'] . '_' . $arField['ID'];
// формируем ошибку, если FORM_ERRORS массив с данными, значит есть ощибка, пытаемся найти ключ перебираемого элемента в массиве с ощибками, нужно для дальнейшей логики
$bHasErrors = (is_array($arResult["FORM_ERRORS"]) && array_key_exists($elementKey, $arResult['FORM_ERRORS']));
?>
<? // формируем обертку инпута ?>
<div class="form__field <?= ($bHasErrors ? 'form__field--error' : ''); ?>">
<? // название ?>
<div class="form__label"><?= $elementValue["CAPTION"] ?></div>
<? // инпут ?>
<input
type="<?= $arField['FIELD_TYPE']; ?>"
class="form-control form__input <?= $elementKey == 'PHONE' ? 'form__input--mask' : ''; ?> <?= ($bHasErrors ? 'form__input--error' : ''); ?>"
placeholder="<?= $elementValue['STRUCTURE'][0]['MESSAGE'] != ' ' ? $elementValue['STRUCTURE'][0]['MESSAGE'] : ''; ?>"
name="<?= $sFieldName; ?>"
value="<?= $arResult['arrVALUES'][$sFieldName] ?>"
<?= $elementValue["REQUIRED"] == "Y" ? 'required' : '' ?>
>
<? // ошибка ?>
<div class="form__error"></div>
</div>
<?php endif; ?>
<?php endforeach ?>
<div class="form__actions">
<input type="hidden" name="web_form_apply" value="Y">
<button class="form__button btn" name="web_form_submit"><?= $arResult["arForm"]["BUTTON"] ?></button>
</div>
<?= $arResult["FORM_FOOTER"] ?>
<?php
// убиваем скрипт
if ($isAjax) {
die();
}
?>
</div>
script.jsBX.ready(function () {
// преобразуем данные, старые компоненты не умеют работать с обьектом FormData
function prepareData(form) {
let formData = new FormData(form);
// добавляем свои параметры для понимания что это Ajax запрос
formData.append('ajax', 'Y');
formData.append('ajax-type', form.name);
let object = {};
formData.forEach((value, key) => object[key] = value);
return object;
}
const form = document.querySelector("form");
form.addEventListener('submit', function (event) {
event.preventDefault();
BX.ajax({
url: form.action,
data: prepareData(form),
method: 'POST',
dataType: 'html',
onsuccess: function (data) {
let parent = document.querySelector('.form')
parent.innerHTML = data;
},
onfailure: function () {
// если запрос не прошел
}
});
})
})
Настройка капчи
Чтобы в форме появилась капча, добавьте в шаблон формы следующий код:
template.php<? if ($arResult["isUseCaptcha"] === true): ?>
<?=$arResult["CAPTCHA_IMAGE"]?><br>
Введите код с картинки:
<?=$arResult["CAPTCHA_FIELD"]?>
<? endif; ?>
В настройках формы в административной панеле, включите показ капчи, на этом капча уже будет работать.
Бывает что код с картинки не читается и пользователь не может отправить форму, поможем пользователю. Вместо кода:
template.php<?=$arResult["CAPTCHA_IMAGE"]?>
Допишем следующие, если пользователь не может прочитать код, он может обновить картинку:
template.php<img src="/bitrix/tools/captcha.php?captcha_sid=<?=$arResult["CAPTCHACode"]?>"
onclick="this.src = '/bitrix/tools/captcha.php?captcha_sid=<?=$arResult["CAPTCHACode"]?>&r='+Math.random()"
style="cursor:pointer"
width="180"
height="40" >
Нажмите на картинку, чтобы обновить
Своя верстка полей через функцию
До этого момента поля в форму мы вставляли HTML_CODE
вопроса, в котором уже содержится код инпута. Давайте его сами генерировать, часто бывает такая необходимость.
Функцию генерации поля ввода объявим как анонимную, чтобы можно было копировать шаблон компонента и не было ошибок на странице, что одна функция объявлена два раза.
Требования к реализации:
- Для поля должен быть указан соответствующий тип
type
- Требуется указать имя поля
name
- Если форма отправлена и были ошибки, значения в поле не должны пропадать
- Если поле обязательно к заполнению, должен быть атрибут
required
- Для полей ввода номера телефона добавим класс
phone
В файле result_modifier.php
шаблона формы добавим такой код:
result_modifier.php<?
if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) {
die();
}
$arResult['funcGetInputHtml'] = function ($question, $arrVALUES, $isFormErrors) {
// ID поля формы
$id = $question['STRUCTURE'][0]['ID'];
// тип поля формы
$type = $question['STRUCTURE'][0]['FIELD_TYPE'];
// имя поля формы
$name = "form_{$type}_{$id}";
// значение введенное пользователем
$value = isset($arrVALUES[$name]) ? 'value="' . htmlentities($arrVALUES[$name]) . '"' : '';
// проверка на обязательное поле
$required = $question['REQUIRED'] === 'Y' ? 'required' : '';
// параметры из админки
$parameters = $question['STRUCTURE'][0]['FIELD_PARAM'];
// плейсхолдер поля формы
$placeholder = $question['CAPTION'] ? 'placeholder=' . '"' . $question['CAPTION'] . '"' : "";
// если поле обязательное, значение value введенное пользователем пустое, при отправке форма вернула ошибку
if ($question['REQUIRED'] == 'Y' && empty($arrVALUES[$name]) && $isFormErrors == 'Y') {
// добавляем класс для подсветки input
$danger = true;
}
switch ($danger) {
// если импут имеет ошибку
case 'true':
$input = "<input type=\"{$type}\" name=\"{$name}\" {$value} {$placeholder} {$parameters} style=\"border-color: red;\" > ";
break;
// если импут без ошибок
default:
$input = "<input type=\"{$type}\" name=\"{$name}\" {$value} {$placeholder} {$parameters} >";
break;
}
return $input;
};
Мы создали функцию, которая попадет в файл template.php
, установили имя, класс из параметров вопроса, атрибут обязательного поля, значение, введенное пользователем.
В template.php
вместо вывода готового HTML кода поля:
template.php<?=$arResult["QUESTIONS"]['NAME']['HTML_CODE']?>
Выведем его через нашу функцию:
template.php<?=$arResult['funcGetInputHtml']($arResult["QUESTIONS"]['NAME'], $arResult['arrVALUES'], $arResult["isFormErrors"])?>
Вместо стандартного вывода, получим новый вывод.
Своя верстка полей в шаблоне
Эта реализация формы очень проста и масштабируема в рамках любой задачи, отдельно обрабатываются скрытые поля и обычные:
<? // подменяем как нам нужно начало формы ?>
<?= str_replace('<form ', '<form class="form__form" ', $arResult["FORM_HEADER"]) ?>
<? // если есть ощибки, обрабатываем ?>
<?php if (!empty($arResult['FORM_ERRORS'])) : ?>
<? // выводим предупреждения ?>
<?php foreach ($arResult['FORM_ERRORS'] as $errorKey => $errorValue) : ?>
<div class="form__danger">
<?= $errorValue; ?>
</div>
<?php endforeach ?>
<?php endif; ?>
<? // формируем тело формы ?>
<?php foreach ($arResult["QUESTIONS"] as $elementKey => $elementValue) : ?>
<? // если поле скрытое ?>
<?php if ($elementValue['STRUCTURE'][0]['FIELD_TYPE'] === 'hidden') : ?>
<? // получаем данные для формирования поля ?>
<?php $arField = reset($elementValue['STRUCTURE']); ?>
<? // формируем инпут ?>
<input type="hidden" name="form_hidden_<?= $arField['ID'] ?>" value="<?= $arField['VALUE']; ?>">
<?php endif; ?>
<? // если поле не скрытое ?>
<?php if ($elementValue['STRUCTURE'][0]['FIELD_TYPE'] != 'hidden') : ?>
<?php
// получаем данные для формирования поля
$arField = reset($elementValue['STRUCTURE']);
// формируем название поля
$sFieldName = 'form_' . $arField['FIELD_TYPE'] . '_' . $arField['ID'];
// формируем ошибку, если FORM_ERRORS массив с данными, значит есть ощибка, пытаемся найти ключ перебираемого элемента в массиве с ощибками, нужно для дальнейшей логики
$bHasErrors = (is_array($arResult["FORM_ERRORS"]) && array_key_exists($elementKey, $arResult['FORM_ERRORS']));
?>
<? // формируем обертку инпута ?>
<div class="form__field <?= ($bHasErrors ? 'form__field--error' : ''); ?>">
<? // название ?>
<div class="form__label"><?= $elementValue["CAPTION"] ?></div>
<? // инпут ?>
<input
type="<?= $arField['FIELD_TYPE']; ?>"
class="form-control form__input <?= $elementKey == 'PHONE' ? 'form__input--mask' : ''; ?> <?= ($bHasErrors ? 'form__input--error' : ''); ?>"
placeholder="<?= $elementValue['STRUCTURE'][0]['MESSAGE'] != ' ' ? $elementValue['STRUCTURE'][0]['MESSAGE'] : ''; ?>"
name="<?= $sFieldName; ?>"
value="<?= $arResult['arrVALUES'][$sFieldName] ?>"
<?= $elementValue["REQUIRED"] == "Y" ? 'required' : '' ?>
>
<? // ошибка ?>
<div class="form__error"></div>
</div>
<?php endif; ?>
<?php endforeach ?>
<div class="form__actions">
<input type="hidden" name="web_form_apply" value="Y">
<button class="form__button btn" name="web_form_submit"><?= $arResult["arForm"]["BUTTON"] ?></button>
</div>
<?= $arResult["FORM_FOOTER"] ?>