[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
643
+26

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

Алексей Соин
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?
        Баха Волков
        07 марта 2023, 15:24
        0
        На данный момент — да, третья версия MODX так долго добиралась, что я и забыл про её существование
          Баха Волков
          07 марта 2023, 15:24
          +1
          Значит скоро будет
            Валерий
            07 марта 2023, 15:53
            0
            Понял :)
            Значит подождем.
          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.
                                Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
                                31