Сохранение формы в Drupal с помощью AJAX
Сегодня речь пойдет о том, как запрограммировать сохранение формы в Друпале через AJAX. В принципе, для этих целей уже существует модуль Ajax. Но вдруг у нас крайне хитрые потребности, или мы просто не хотим ради сабмита пары форм тащить за собой целый модуль?
В общем, задача такова: создать средствами Друпала простую форму, вывести ее на страницу, а затем — сохранять через AJAX-запросы, выводя на ту же страницу результаты сохранения и ошибки валидации формы, если таковые были. Без обновления страницы, естественно. Для решения задачи будем использовать Form API Друпала и jQuery с плагином Form. Оформим все в виде отдельного модуля.
Рассмотрим решение по порядку. Начнем с создания страницы с формой.
Теперь если пользователь зайдет по адресу /jf_test, напишет что-нибудь в форме и нажмет «Отправить», набранный текст будет накапливаться в блоке под надписью «Сообщения». Пока отправка текста происходит обычным сохранением формы с перезагрузкой страницы. Сделаем, чтобы сообщения отправлялись с помощью AJAX.
Прежде всего, нужно добавить скрипт с плагином jQuery Form. Сама библиотека jQuery включена в Друпал и добавится автоматически. Плагин Form тоже включен в состав Друпала, но версия очень старая, а мы скачаем новую и подключим ее при генерации страницы. Заодно сразу добавим js-файл со скриптом, которым будем сохранять форму.
Теперь напишем сам скрипт jf_test.js:
Drupal.behaviors заменяет $(document).ready()
Затем мы устанавливаем для события submit, то есть сохранения формы, свой обработчик. В нем возвращается false — для того чтобы избежать обычного сохранения с обновлением страницы. Ну а в функции successCallback мы добавляем в блок «Сообщения» тот текст, который получили от сервера.
Однако, если мы попытаемся выполнить все, что написали, то увидим, что в блок «Сообщения» добавилось не последнее введенное сообщение, а целая страница, сгенерированная Друпалом заново. Поэтому теперь нам нужно позаботиться об адекватных ответах на AJAX-запросы при сохранении формы. То есть, нужно возвращать не всю страницу, а только последнее введенное сообщение. Кроме того, мы бы хотели получать сообщения об ошибках валидации формы, которые возникнут, например, если мы оставим поле ввода сообщения пустым. Для этого напишем валидатор нашей формы, а также немного изменим функцию сохранения:
Теперь мы получаем от сервера либо последнее сообщение пользователя, либо ошибку валидации. Окончательный jf_test.js выглядит так:
На всякий случай уточняю: функции ajaxForm и resetForm — это функции из API плагина jQuery Form, без него ничего работать не будет.
Наконец, позаботимся о злоумышленниках, коварно отключивших в своих браузерах JavaScript. Ведь если оставить все как есть, после сохранения формы они будут видеть только текст последнего сообщения и больше ничего. Чтобы все работало нормально и без JavaScript-а, будем проверять способ сохранения формы в функциях валидатора и сохранения. Окончательный текст этих функций:
Теперь с выключенным JavaScript-ом все будет работать так, как будто его и не было никогда. Задача решена.
Рабочие исходники — прилагаются.
| Прикрепленный файл | Размер |
|---|---|
| jf_test.tar.gz | 8.82 кб |
Спасибо, за статья. Мне такая проблема. Я сам написал AJAX внутри тема. Но в AJAX e я получаю целая страница. Как можно решит эту проблему.
В статье эта проблема рассматривается. Найдите слова «не всю страницу», там написано, что делать. Подробнее пока не могу написать — с телефона неудобно.
Если надо подробнее, скажите, через пару дней смогу ответить.
Можно ли сделать не сохранение введенного параметра, а что-то наподобие превью. Т.е. при перезагрузке, на странице находится лишь информация данная по-умолчанию. А после, отправки данных из формы информация изменяется (вместо дефолтной пропечатывается новая, и так каждый раз по субмиту). После перезагрузки страницы — снова деволтное значение (которое формируется из данных аргумента в адресе страницы).
Спасибо.
Можно, конечно. Надо только в скрипте вместо аппенда нового содержимого к старому сделать замену старого содержимого новым (напр. .html(responseText)).
А в остальном это скорее вопрос изначальной генерации страницы, к аяксу особого отношения не имеет.
Спасибо, так работает. Вопрос же по генерации старницы возник из-за того, что данные накапливаются в базе данных. Для работы через аякс в этом случае необходимо именно таким образом сохранять, чтобы потом выводить на страницу? Извините за ламерские вопросы.
Нет, как мы сохраняем и загружаем данные — к аяксу вообще отношения не имеет, важно, что мы передаем браузеру при сабмите формы.
Есть следующая проблема. При загрузке с помощью AJAX теряется CSS-оформление данных и их связка с JS-скриптом, которые вызываются только при первой загрузке всей страницы. Т.е. речь наверное идет об организации процесса Lazy-load. На Drupal.org нашел некоторые ссылки по этой теме, но не могу это применить (за основу взял пример этого поста и разместил выводимую после сабмита информацию в табах на jQuery).
Ссылки:
jQuery plugin to lazy load other plugins. Small and easy to use.
Improve performance with JavaScript lazy loading.
Что можно сделать для решения данной проблемы?
Также, существует модуль AJAX load Но, автоматом он не включился в решение задачи, а с документацией на английском тяжеловато.
Сходу не понять, надо разбираться, а у меня сейчас времени нет. Создайте тему на drupal.ru, так быстрее помогут.
Спасибо за статью.
Подскажите, как сделать, чтобы при сабмите в форме сохранялось выбранное значение? Сейчас оно сбрасывается.
Речь о сохранении значения или о показе сохраненного ранее при выводе формы? Что за выбранное значение — селект? Что значит сбрасывается? Выражайте свои мысли яснее, пожалуйста :)
Если речь о сохранении значения — сохранять надо в функции сабмита формы.
Если речь о выводе установленного ранее значения в форме — надо пользоваться свойством #default_value.
Речь о показе выбранного и установленного после самбита значения в select и checkbox полях формы.
Использовал:
'#default_value' => array_search(variable_get('jft_messages', $message), $options_for_select)
Но в данном случае не срабатывает. Разве сама форма при использовании АЯКса перезагружается для того, чтобы воспользоваться функцией variable_get или !_POST при показе дефолтного значения?
Уже думается, что это делать надо в JS.
Спасибо за ответ.
Так если вы сабмиттите форму через аякс, просто не сбрасывайте ее при сабмите — тогда выбранные до сабмита значения останутся на месте.
И — нет, конечно форма не перезагружается, если вы в JS не скажете ее перезагружать.
Да! Разобрался:)












Спасибо за информацию. Очень помогла))