[FetchIt] - Полноценная замена AjaxForm без зависимостей

Представляю вашему вниманию новый бесплатный компонент MODX Revolution для обработки и отправки форм, который пришёл на замену AjaxForm. И давайте начнём сразу с преимуществ и различий:




FetchIt не имеет никаких зависимостей, тогда как у AjaxForm их три:

  1. Большая библиотека jquery.
  2. Плагин для работы с формами jquery-form.
  3. И jGrowl для показа уведомлений.
Минифицированный скрипт весит 5 килобайт и сниппет регистрирует его с атрибутом defer тем самым не мешая загрузке страницы.

Встраивание вашей вёрстки, добавление всплывающих сообщений и модальных окон, это задачи которые Вы сможете решить очень просто.

Почему не AjaxForm 2.0.0?


Сразу отвечу на этот предсказуемый вопрос, ведь я в организации modx-pro и мог бы выпустить новую мажорную версию и разработчики могли бы обновиться. Причин два: во-первых это название – AjaxForm, дело в том, что аббревиатура AJAX которая расшифровывается как Asynchronous Javascript and XML для данного компонента не подходит, он для отправки форм использует Fetch API. Во-вторых, изменения большие и обратную совместимость всё равно сохранить было невозможно.

Быстрый старт


Для быстрого старта Вам необходимо вызвать сниппет FetchIt который идёт в компоненте, передав ему основные параметры которые совпадают по названию с параметрами AjaxForm.

[[!FetchIt?
  &snippet=`FormIt`
  &form=`myForm.tpl`
  &hooks=`email`
  &emailSubject=`Тема письма`
  &emailTo=`info@domain.com`
  &validate=`name:required,email:required`
  &validationErrorMessage=`В форме содержатся ошибки!`
  &successMessage=`Сообщение успешно отправлено`
]]

или на fenom

{'!FetchIt' | snippet : [
  'snippet' => 'FormIt',
  'form' => 'myForm.tpl',
  'hooks' => 'email',
  'emailSubject' => 'Тема письма',
  'emailTo' => 'info@domain.com',
  'validate' => 'name:required,email:required',
  'validationErrorMessage' => 'В форме содержатся ошибки!',
  'successMessage' => 'Сообщение успешно отправлено',
]}

Миграция с AjaxForm


На сайте с документацией есть подробное описание миграции, но тут опишу вкратце. Параметры frontend_css и formSelector убраны за ненадобностью, а frontend_js и objectName были перемещены в системные настройки и называются fetchit.frontend.js и fetchit.frontend.js.classname соответственно.

Компонент не регистрирует стили. Так что вам самим нужно позаботиться о них (речь о стилях отвечающих за невалидным состоянием полей). Есть две настройки fetchit.frontend.input.invalid.class и fetchit.frontend.custom.invalid.class отвечающие за добавление классов полям ввода и кастомным элементам (например элементам-обёрткам).

Вывод всплывающих сообщений также перекладывается на плечи самих разработчиков, но реализация максимально простая и в документации уже есть подробные примеры популярных и не очень библиотек: SweetAlert2, Notyf, iziToast, Notiflix.Notify, Notie, Awesome Notifications, Toastify JS, AlertifyJS, PNotify, toastr и даже наш любимый jGrowl.

Изменились селекторы, теперь не используются CSS классы, которые предназначены для определения стилей. Вместо них дата-атрибуты. Опять же, призываю вас на сайт документации, где подробно описаны примеры типовых решений разметок Bootstrap, Bulma, UIkit, Fomantic-UI, Pico.css, Cirrus CSS, turretcss и Vanilla.

Если у вас была какая-то логика связанная с отправкой формы (Например, дополнительная отправка данных в CRM или аналитические сервисы и метрики), то нужно будет немного переписать. jQuery больше нет и у AjaxForm было одно событие на фронте, а в FetchIt их пять:

Ниже пример в котором добавляется новое поле перед отправкой формы:

document.addEventListener('fetchit:before', (e) => {
  const { formData } = e.detail;

  formData.set('newField', 'Значение нового поля'); // Добавляем новое поле
})

или отправляем данные в CoMagic после успешной отправки формы:

document.addEventListener('fetchit:success', (e) => {
    const { formData } = e.detail;

    Comagic.addOfflineRequest({
        name: formData.get('name'),
        email: formData.get('email'),
        phone: formData.get('phone'),
        message: formData.get('message'),
        group_id: 1234
    });
})

На этом думаю пока что достаточно, как уже несколько раз было упомянуто выше, больше примеров и описание API на сайте с документацией. Компонент уже доступен для установки на маркетплейсе modstore.pro и modx.com.

Сайт с документацией
Репозиторий на GitHub
☕ Угостить чашкой кофе
Баха Волков
02 марта 2023, 14:02
modx.pro
6
1 336
+26

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

Алексей Соин
02 марта 2023, 20:33
+2
Уже успел опробовать))) Компонент суперский, спасибо! И отдельное спасибо за отличную документацию)
    Баха Волков
    02 марта 2023, 21:21
    +6
    Документацию писал в три раза дольше чем сам компонент 🙄
    Misha Bulic
    03 марта 2023, 13:44
    0
    Крутая Дока, надо будет какой нибудь сайт перевести.
    Вопрос: есть ли какая то реализация антиспама?
      Баха Волков
      03 марта 2023, 14:19
      0
      Вопрос: есть ли какая то реализация антиспама?
      Ситуация ровно такая же как и с AjaxForm. Например компонент reCaptchaV3 отработает точно также.
      Валерий
      07 марта 2023, 15:14
      0
      День добрый.
      Компонент только для ModX 2?
      grotesqueman
      10 марта 2023, 03:15
      0
      приветствую
      компонент работает, только в журнал ошибок сыпет:
      (ERROR @ ...\core\cache\includes\elements\modsnippet\41.include.cache.php : 53) PHP warning: Undefined variable $hash
      ERROR @ ...\core\components\fetchit\model\fetchit.class.php : 94) PHP warning: Undefined array key ""
      MODX Revolution 2.8.4-pl
      PHP Version 8.1.10
        Баха Волков
        10 марта 2023, 09:46
        0
        Спасибо за отклик!

        Исправил.

        Версия 1.0.0 доступна на modstore.pro
        Она же будет доступна после модерации на modx.com
        Сергей
        10 марта 2023, 12:23
        0
        Ребята, подскажите, почему может не срабатывать параметр: clearFieldsOnSuccess?
        Вызов такой:
        {'!FetchIt' | snippet : [
                    'snippet' => 'FormIt',
                    'form' => 'tpl_form_popup',
                    'emailTpl' => 'tpl_email',
                    'hooks' => 'FormItSaveForm,email',
                    'emailTo' => $_modx->config.email_address,
                    'emailFrom' => $_modx->config.email,
                    'aliases' => 'phone==Телефон,name==Имя',
                    'emailSubject' => 'Заявка на консультацию с сайта',
                    'validate' => 'name:required:minLength=^5^,phone:required:minLength=^17^',
                    'validationErrorMessage' => 'В форме содержатся ошибки!',
                    'name.vTextRequired' => 'Укажите ФИО.',
                    'name.vTextMinLength' => 'Слишком короткое ФИО.',
                    'phone.vTextRequired' => 'Укажите телефон.',
                    'phone.vTextMinLength' => 'Слишком короткий телефон.',
                    'successMessage' => 'Сообщение успешно отправлено',
                    'clearFieldsOnSuccess' => 1,
                ]}
          Баха Волков
          10 марта 2023, 13:22
          0
          Нужны уточнения:

          1. Всё остальное работает? Отправляется ли форма, работает ли валидация?

          2. Сколько вызовов FetchIt есть на странице? Если больше одного, то покажи их тоже.

          3. Есть ли в консоли js какие-то ошибки?
            Сергей
            10 марта 2023, 14:21
            0
            1. Все остальное работает. Валидация работает, форма отправляется, событие на успешную отправку срабатывает.
            2. Один вызов FetchIt на странице
            3. В консоли браузера ошибок нет, в админке тоже

            Но вот что за прикол не знаю, только что проверил отправку и все сработало и форма очистилась…
            Интересный прикол.
            Баха Волков
            10 марта 2023, 18:39
            0
            Проверил и не смог подтвердить, причем параметр clearFieldsOnSuccess по умолчанию включен и поля должны очищаться. Полагаю, что были ошибки в кастомных js и из-за них ломалось поведение.
            UDAV
            13 марта 2023, 11:34
            0
            За модуль спасибо!
            Но не понятно в чем преимущество удаления зависимости от jquery?
            99% сайтов на modx используют эту либу.
            Да и говорить что она огромная, это смешно, по сути весит как одна картинка на любом сайте да и в браузере уже у всех в кеше есть.
              Артур Шевченко
              13 марта 2023, 11:44
              +2
              Разница между картинкой в 100кб и скриптом того же размера в том, что скрипт надо не только загрузить, но ещё проанализировать и выполнить. Поэтому отсутствие jQuery это неслабый буст для загрузки сайта. А в целом, никто вас не заставляет отказываться от jQuery. Развитие и стремление к совершенству это внутренняя потребность личности, не всем она присуща.
                Баха Волков
                13 марта 2023, 14:27
                +1
                За модуль спасибо!
                Пожалуйста!

                Но не понятно в чем преимущество удаления зависимости от jquery?
                Я (очень) далеко не первый кто прыгает в поезд тенденции отказа от jQuery, которая возникла по объективным причинам. Главная из которых: сам JavaScript её почти/уже догнал по функционалу и удобству.

                Использовать jQuery только чтобы навесить один обработчик на событие и добавить/удалить css класс с нескольких элементов — это одеть медведя в меховую шубу! Вот если вы сфинкс в Сибири, то надевать шубу (использовать jQuery) имеет смысл.

                99% сайтов на modx используют эту либу.
                Ну и прекрасно, но это к чему? Это же аргумент в пользу FetchIt. Следите за руками:

                — Если (как вы утверждаете) 99% сайтов на MODX используют jQuery, то AjaxForm будет работать на 99% сайтах, остальным сайтам (1%) которые без jQuery, придется тянуть зависимость только чтобы работал AjaxForm.

                — Если (как вы утверждаете) 99% сайтов на MODX используют jQuery, то FetchIt будет работать на 100% сайтах, даже у тех где используется jQuery.

                Да и говорить что она огромная, это смешно, по сути весит как одна картинка на любом сайте да и в браузере уже у всех в кеше есть.
                На это уже @Артур Шевченко ответил, но я дополню, больше не для вас, а для всех кто так думает. FetchIt делает больше и лучше за 300 строчек кода чем AjaxForm за более чем 12 000.
                  UDAV
                  13 марта 2023, 15:10
                  0
                  спасибо за развернутый ответ, надо переосмыслить подход и возможно тоже отказываться от жквери.
                Баха Волков
                20 марта 2023, 21:28
                0
                На данный момент есть баг связанный с вызовом сниппета на fenom, завтра выпущу патч с исправлением.
                  Лёша
                  21 марта 2023, 12:00
                  0
                  @Артур Шевченко а в чём смысл AjaxFormitLogin сейчас? Я так понял эти компоненты идентичны. Ни разу не использовал AjaxForm, так что вопрос — а можно показывать сообщение об успешной отправке в самой форме? Отправляешь форму и как будто ничего не происходит, jgrowl довольно сложно заметить на экране (да, jgrowl можно заменить, но всё же)
                    Баха Волков
                    21 марта 2023, 13:10
                    +1
                    так что вопрос — а можно показывать сообщение об успешной отправке в самой форме?
                    Да, легче легкого. Например, в чанке формы указываете какой-то элемент:

                    <form id="form-1">
                        <!-- какая-то разметка -->
                        <div class="successMessage"></div>
                        <!-- какая-то разметка -->
                    <form>
                    
                    document.addEventListener('fetchit:success', (e) => {
                      const { form } = e.detail;
                    
                      if (form.getAttribute('id') === 'form-1') {
                        const successMessage = form.querySelector('.successMessage');
                        successMessage.innerHTML = 'Форма отправлена';
                    
                        // И вообще, делаете что хотите
                      }
                    });

                    Именно поэтому я реализовал JS API (документация) таким образом, чтобы можно было реализовать разные сценарии.

                    Кстати, в версии альфа такая возможность была в коробке, но я выпилил в пользу API, но если люди захотят, то могу вернуть эту возможность.
                      Баха Волков
                      21 марта 2023, 13:21
                      +1
                      Я так понял эти компоненты идентичны
                      Проблем у AjaxFormitLogin множество.

                      • Отсутствие API
                      • Нехватка событий (есть одно afl_complete) что не позволяет решать разные задачи
                      • Повторение недостатка AjaxForm (AjaxForm тянул зависимость ввиде jgrowl, а AjaxFormitLogin теперь тянет iziToast)
                      • Самое главное, AjaxFormitLogin заменил громоздкий jquery-form на XMLHttpRequest — это нонсенс
                        Артур Шевченко
                        21 марта 2023, 15:19
                        +1
                        Отсутствие API
                        Какой API нужен компоненту для отправки форм ajax'ом?

                        Нехватка событий (есть одно afl_complete) что не позволяет решать разные задачи
                        Какие задачи связанные с отправкой формы нельзя решить используя AjaxFormitLogin?

                        Повторение недостатка AjaxForm (AjaxForm тянул зависимость ввиде jgrowl, а AjaxFormitLogin теперь тянет iziToast)
                        AjaxForm тянул jQuery и jGrowl, AjaxFormitLogin тянет IziToast только для того, чтобы из коробки были уведомления. В документации написано как отключить их и заменить.

                        Самое главное, AjaxFormitLogin заменил громоздкий jquery-form на XMLHttpRequest — это нонсенс
                        Fetch API не позволяет отслеживать процесс загрузки файлов, а мне это нужно.
                          Баха Волков
                          21 марта 2023, 18:11
                          +1
                          Какой API нужен компоненту для отправки форм ajax'ом?
                          Банально — такой, такой и такой

                          Какие задачи связанные с отправкой формы нельзя решить используя AjaxFormitLogin?
                          Добавление и/или изменение значений отправляемых на сервер, например. Или ты хочешь предложить манипулировать DOM для этого?

                          AjaxForm тянул jQuery и jGrowl, AjaxFormitLogin тянет IziToast только для того, чтобы из коробки были уведомления. В документации написано как отключить их и заменить.
                          Ну мне то объяснять уж не стоило. Ответ на вопрос «Почему?» я знаю, тут другой несколько вопрос «Зачем?». Каждый раз когда зависимость обновиться, нужно будет обновить компонент? Ну прикольно. А еще бывают «прикольные приколы», когда разработчик sweetalert2 захочет выразить свой личный протест в OpenSource проекте, то как быть с этим?

                          Тут важно, не каждая зависимость это плохо, но это тот самый случай, когда легко и безболезненно можно обойтись и без него.

                          Fetch API не позволяет отслеживать процесс загрузки файлов, а мне это нужно.
                          Позиция ясна. А это единственная причина? Fetch API пока не позволяет. Но знаешь в чём загвоздка? Работа над введением этой возможности ведётся и оно точно появится, а ведётся ли работа над асинхронностью в XMLHttpRequest?
                            Артур Шевченко
                            21 марта 2023, 18:40
                            +1
                            Банально — такой, такой и такой
                            Думаю это ни к чему в данном компоненте, просто потому что я не могу придумать для чего это может понадобиться лично мне. А добавлять что-то, чтобы было такое себе. Если кто-то предложит PR, волью без проблем.

                            Добавление и/или изменение значений отправляемых на сервер
                            Грубо говоря да, но при желании всегда можно расширить класс.

                            Каждый раз когда зависимость обновиться, нужно будет обновить компонент?
                            Нет смысла обновлять то, что и так работает.

                            когда разработчик sweetalert2 захочет выразить свой личный протест в OpenSource проекте, то как быть с этим?
                            Понятное дело не использовать подключение зависимостей через cdn.

                            Работа над введением этой возможности ведётся и оно точно появится
                            Когда такая возможность появится — перепишу.
                              Баха Волков
                              21 марта 2023, 19:17
                              +2
                              просто потому что я не могу придумать для чего это может понадобиться лично мне. А добавлять что-то, чтобы было такое себе.
                              Ну Артур, ну какой ты молодец. Добавлять авторизацию и регистрацию — это не «такое себе», просто я не понял и это вообще другое.

                              Хорошо, ты не смог придумать, а я представь — смог. Тык, тык и тык.

                              Грубо говоря да, но при желании всегда можно расширить класс.
                              Прости, но мне придётся поязвить — ты же обязательно покажешь как расширить класс? Т.е. для простой задачи добавить и/или изменить значение в форму перед её отправкой, нужно манипулировать с DOM или расширить класс? Прикольно.

                              Нет смысла обновлять то, что и так работает.
                              Я уже понял. Именно с этим лозунгом ты сменил jquery-form на XMLHttpRequest

                              Когда такая возможность появится — перепишу.
                              Ты проигнорировал вопрос про асинхронность в XMLHttpRequest, но это приводит к более веселой ситуации: А когда в XMLHttpRequest появится (спойлер — не появится, но есть библиотеки-обёртки над ним в которых реализована асинхронность) ты обратно перепишешь с Fetch API на XMLHttpRequest?
                                Артур Шевченко
                                21 марта 2023, 20:05
                                +1
                                Добавлять авторизацию и регистрацию — это не «такое себе»
                                Не такое себе, я этим пользуюсь, мне удобно когда это есть.

                                Т.е. для простой задачи добавить и/или изменить значение в форму перед её отправкой, нужно манипулировать с DOM или расширить класс?
                                Я согласен, что это не самое удобное решение, но вынужден повторить — в моей практике нечасто встречаются кейсы требующие манипулировать значениями перед отправкой, поэтому я и не добавил дополнительных событий.

                                Именно с этим лозунгом ты сменил jquery-form на XMLHttpRequest
                                Нет, лозунг был другой: одна отключаемая зависимость лучше двух обязательных.

                                Ты проигнорировал вопрос про асинхронность в XMLHttpRequest
                                Потому что счёл его риторическим, логично же что никаких работ по усовершенствованию не ведётся, разработан новый API и его развивают.

                                А когда в XMLHttpRequest появится (спойлер — не появится, но есть библиотеки-обёртки над ним в которых реализована асинхронность) ты обратно перепишешь с Fetch API на XMLHttpRequest?
                                Ты меня за идиота принимаешь? Я решаю возникающие у меня задачи, удобным для меня способом. Мне нужно показывать процесс загрузки, Fetch API этого не умеет, я использовал XMLHttpRequest. По-моему всё логично.

                                Мне кажется ты упускаешь суть: ты писал компонент с целью внедрения Fetch API, я писал компонент с целью повысить удобство собственной работы и отказаться от использования jQuery. Не вижу причин по которым я обязан был использовать Fetch вместо XMLHttpRequest. Для пользователя компонента это вообще не важно, что там под капотом, главное это стабильное выполнение необходимых ему функций.

                                И наконец, всё что ты перечислил в качестве проблем AjaxFormitLogin, всего лишь твоё скромное мнение, о чем ты забыл упомянуть, отчего кому-то может показаться, что перечисленные тобой «проблемы» действительно серьезно могу усложнить жизнь пользователю моего компонента. Я думаю тот, кому понадобится больше событий и API, легко поймёт, что всё это есть в FetchIt, и выберет именно его.
                        Артур Шевченко
                        21 марта 2023, 15:11
                        0
                        В AjaxFormitLogin нет jGrowl, там IziToast. Можно заглянуть к нему в документацию и настроить как хочется, или расширить класс уведомлений и написать свои.
                          Артур Шевченко
                          21 марта 2023, 15:22
                          +1
                          а в чём смысл AjaxFormitLogin сейчас
                          В том, что этот компонент упрощает мне разработку сайтов, там много всякой функциональности, которая нужна почти на каждом сайте. А вообще, читайте документацию, чтобы решить надо оно вам или нет.
                          exist17
                          21 марта 2023, 22:04
                          0
                          Вопрос. Компонент использует сессии для хранения параметров так же как AjaxForm или этот момент решен как то иначе?
                            Баха Волков
                            22 марта 2023, 11:22
                            0
                            В серверной части FetchIt практически является форком AjaxForm.
                            Константин Ильин
                            17 мая 2023, 11:47
                            0
                            Баха, подскажи пожалуйста, что-то никак не соображу как подключить свой файловый сниппет, такие вызовы не срабатывают
                            'snippet' => '@FILE snippets/snippet.php',
                            /* или */
                            'snippet' => 'file:snippets/snippet.php',
                            Причем для Формы файловая «ссылка» срабатывает
                            'form' => '@FILE chunks/forms/zayavka.form.tpl'
                            Ivan
                            20 мая 2023, 19:11
                            0
                            Есть какая-нибудь информация по срокам появления поддержки modx3? Спасибо
                              Баха Волков
                              24 мая 2023, 19:03
                              +1
                              Есть какая-нибудь информация по срокам появления поддержки modx3? Спасибо
                              1. Данный компонент отлично работает с MODX 3, с одним, но — не работают файловые чанки и вы можете установить его вручную скачав транспортный пакет с github.

                              2. Есть черновой вариант полной поддержки MODX 3, но я занят по работе и кое-что масштабное готовлю для сообщества.

                              Как будет время доделаю
                                  Ivan
                                  11 июня 2023, 11:20
                                  0
                                  Отлично. Спасибо!
                                Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
                                40