Простой опросник с ветвлением (AjaxForm + FormIt + MIGX + pdoTools)

По традиции, для тех, кто не любит заморачиваться, сообщаю, есть готовый компонент Quiz. Сам я им не пользовался, но из описания следует, что по функционалу он очень похож.
Теперь коротко о том, зачем я всё это затеял. Первая версия моего опросника была сделана для собственного сайта и не предполагала ветвления, и я решил это исправить, в основном, чтобы попрактиковаться. Поэтому конструктивная критика приветствуется.
Исходники можно скачать отсюда.

ВЕСЬ КОД НИЖЕ ВКЛЮЧЁН В КОМПОНЕНТ SENDIT



Итак, первое что нужно сделать это установить компоненты AjaxForm, FormIt, MIGX, pdoTools. AjaxForm требует подключения jQuery, поэтому её тоже нужно подключить (см. файл core/elements/pages/index.html из архива). Либо взять вариантAjaxForm без jQuery.
Верстка по большей части значения не имеет, главное сохранить вложенность классов с префиксом «js». Для простоты, я подключил Bootstrap 5. Также отмечу, что есть классы для скрытия элементов «d-none» и «visually-hidden», это классы из Bootstrap, но вы можете указать свои, передав при инициализации опросника в js вторым параметром объект с нужными значениями (полный список значений конфигурации смотри в файле assets/js/quiz.js).
new Quiz('.jsQuizForm', {
 displayNoneClass: 'd-none',
 hiddenClass: 'visually-hidden'
});
Далее, нужно создать конфигурации MIGX.
1. quizItem — конфиг вопроса
2. answer — конфиг ответа
3. quiz — общий для опроса конфиг
4. field — конфиг для полей с данными пользователя
5. validator — конфиг валидатора (можно использовать валидаторы как в FormIt, по умолчанию список неполный).
6. add_for_item — здесь можно указать путь к картинкам и подписи к ним, чтобы «оживить» квиз. Дополнительные элементы связаны с вопросами по MIGX_id и необязательны.

Для каждого вопроса есть возможность задать варианты ответа, даже если это текстовое поле или область, понимаю что с одной стороны это нелепо, а с другой в MIGX сложную логику реализовать сложно, к тому же это необходимо для организации ветвлений. Для каждого варианта ответа можно указать ID следующего вопроса, который указан в таблице добавленных вопросов, если этого не сделать, то следующим вопросом будет тот, что идёт в списке сразу после текущего. Ветвление лучше вешать на поле типа Переключатель. Если повесить на поле типа checkbox, переход будет осуществлен к тому значению, которое соответствует последнему выбранному чекбоксу. Так же есть возможность включить автопереключение, для чекбоксов не рекомендую этого делать, т.к. они предполагают выбор нескольких вариантов, а переключение срабатывает на событие change, т.е. переход сработает после выбора первого чекбокса.

Вызов сниппета getQuiz выглядит так
{$_modx->runSnippet('@FILE: snippets/getQuiz.php', [
'rid' => $_modx->resource.id, // id ресурса из которого брать опросники.
'quizID' => 2 // ID опросника указанный в таблице
])}
Остальные параметры, например чанки, задаются для каждого квиза индивидуально. Для этого в конфигурации quiz есть вкладка Служебные по умолчанию там только один шаблон — стандартный, дополнить список можно только вручную, отредактировав конфигурацию.

На одной страницы может быть сколько угодно опросов, но каждому из них нужен уникальный идентификатор, который указывается при создании экземпляра класса.
Обращаю ваше внимание на то, что чанк письма содержит элементы непривычного синтаксиса, это связано с тем, что заранее нам неизвестны имена полей и их количество, поэтому при вызове сниппета чанк письма парсится и в нём появляются указанные в админке поля, а уже в вызов ajaxForm он попадает как инлайн-чанк, где "##" заменено на "{", что позволяет при отправке формы вставить в него данные пользователя.
Есть возможность сделать ответы на вопросы обязательными.
При переключении вопросов на форме генерируется событие question_change поймать его можно так
document.querySelector('.jsQuizForm').addEventListener('question_change', (e) => {
    let  e.detail.items, // все вопросы
         e.detail.target, // следующий вопрос
         e.detail.curIndex, // индекс текущего вопроса
         e.detail.direction, // направление (вперёд или назад)
         e.detail.btnBack, // элемент кнопки НАЗАД
         e.detail.btnForward, // элемент кнопки ВПЕРЁД
         e.detail.btnSubmit, // элемент кнопки ОТПРАВИТЬ
         e.detail.activeItem; // активный элемент
});
Посмотреть как это работает можно тут
Артур Шевченко
13 ноября 2021, 15:27
modx.pro
5
1 635
+8
Поблагодарить автора Отправить деньги

Комментарии: 0

Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
0