Я работаю над реализацией Ajax для отправки веб-формы на Drupal 7. Мне не удалось найти ничего хорошего, hook
чтобы изменить кнопку отправки веб-формы и добавить «#ajax» в форму, поэтому я посмотрел на модуль Drupal 6, который реализует эту функциональность из внешнего скрипта.
Поэтому я решил пойти со своим собственным модулем и кодом JavaScript для запуска пост-запроса Ajax в обратный вызов пользовательского меню, который я определил hook_menu()
в Drupal 7.
Часть JavaScript работает нормально, но у меня возникают проблемы при попытке отправить веб-форму программно.
Вот мой код JavaScript:
function formSubmit(event, formId) {
event.preventDefault();
var form = jQuery("#" + formId);
var postData = form.serialize();
var nodeId = formId.substring(20);
var msg = '';
msg += form.find('#edit-submitted-name').attr('value') ? '' : 'Please enter your name';
console.log(form.find('#edit-submitted-name').attr('value'));
console.log(form.find('#edit-submitted-e-mail').attr('value'));
if(msg) {
alert(msg);
} else {
jQuery.ajax({
url: Drupal.settings.basePath + 'webform_ajax/' + nodeId,
fid:formId,
type: 'POST',
data: postData,
success: function(ajaxData) {
console.log(ajaxData);
console.log('Hello world');
// can't get here
}
});
}
}
И мой код модуля (на основе модуля webform_ajax):
function custom_menu() {
$items = array();
$items['webform_ajax/%'] = array(
'page callback' => '_custom_webform_ajax',
'page arguments' => array(1,2),
'access callback' => '_custom_webform_ajax_access',
);
return $items;
}
function _custom_webform_ajax($nid, $data) {
//$sid = $_POST['details']['sid'];
$local_POST = $_POST;
$form_build_id = $_POST['form_build_id'];
$form_id = 'webform_client_form_' . $nid;
$node = node_load($nid);
$submission = array();
$form_state = array();
$form = form_get_cache($form_build_id, $form_state);
$form_array = drupal_rebuild_form($form_id, $form_state, array($form_state, $node, $submission), $form_build_id);
$form_state['clicked_button'] = $form_array['actions']['submit'];
if (is_array($local_POST['submitted'])) {
foreach ($local_POST['submitted'] as $submit_index => $submit) {
$form_state['storage']['submitted'][$submit_index] = $submit;
$form_state['values']['submitted'][$submit_index] = $submit;
}
}
// Clearing empty values from $form_state
if (is_array($form_state['values']['submitted'])) {
foreach ($form_state['values']['submitted'] as $value_index => $value) {
if (!$value) {
unset($form_state['values']['submitted'][$value_index]);
}
}
}
// Executing the pressed button action
drupal_execute($form_id, $form_state, $node, array());
// Get the HTML for the error messages
$error_html = theme('status_messages', 'error');
// Building the resulting form after the processing of the button
$form_array = drupal_rebuild_form($form_id, $form_state, array($form_state, $node, $submission), $form_build_id);
$form = drupal_render_form($form_id, $form_array);
return drupal_json_output(array(
'message' => $error_html,
'status' => 'sent',
));
}
function _custom_webform_ajax_access() {
// Todo: Add webform access conditions
return true;
}
Когда я отправляю свою форму, я получаю 500 ошибок сервера.
Я полагаю, что API форм D6 и D7 совершенно разные, и я не уверен, с чего начать, чтобы этот кусок кода работал. Я пытался отладить его, но я не могу понять, что вызывает 500 ошибок.
Я использую webform 3, и модуль, который я взял, также использует версию 3 webform, но для Drupal 6. Но оба модуля должны обеспечивать те же функции и те же функциональные возможности. Первый обходной путь: это может происходить из значений, которые я передаю, которые не совместимы с формой API D7.
В моем журнале у меня есть:
Argument 1 passed to drupal_array_nested_key_exists() must be an array, null given, called in D:\wamp\www\productionsite\includes\form.inc on line 1986 and defined in drupal_array_nested_key_exists() (line 6296 of D:\wamp\www\productionsite\includes\common.inc).
-- РЕДАКТИРОВАТЬ --
Сейчас я отлаживаю построчно, в конце этот кусок кода может стать модулем D7;)
В документации D7 я обнаружил, что аргументы drupal_rebuild_form () изменились с D6, и что $form_state
на этом этапе больше не может быть пустым, поэтому я обновил свой код следующим образом:
$form_state = array('submitted' => false, 'values' => array());
$form = form_get_cache($form_build_id, $form_state);
$form_array = drupal_rebuild_form($form_id, $form_state, $form);
Теперь я пытаюсь найти эквивалент drupal_execute (), которого больше нет в D7.
- Изменить (2) -
Я получил его несколько дней назад и вернулся, чтобы поделиться решением, и, возможно, получить некоторые советы и предложения по улучшению.
<?php
function custom_menu() {
$items = array();
$items['webform_ajax/%'] = array(
'page callback' => '_custom_webform_ajax',
'page arguments' => array(1,2),
'access callback' => '_custom_webform_ajax_access',
);
return $items;
}
function _custom_webform_ajax($nid, $data) {
$local_POST = $_POST;
$form_build_id = $_POST['form_build_id'];
$form_id = 'webform_client_form_' . $nid;
$node = node_load($nid);
$submission = array();
$form_state = array(
'submitted' => false,
'values' => array(),
'build_info' => array(
'args' => array(
$node,
array(),
FALSE
)
)
);
$form = form_get_cache($form_build_id, $form_state);
$form_array = drupal_rebuild_form($form_id, $form_state);
// Add the clicked button before processing the form
$form_state['clicked_button'] = $form_array['actions']['submit'];
if (is_array($local_POST['submitted'])) {
foreach ($local_POST['submitted'] as $submit_index => $submit) {
$form_state['values']['submitted'][$submit_index] = $submit;
}
}
// Clearing empty values from $form_state
if (is_array($form_state['values']['submitted'])) {
foreach ($form_state['values']['submitted'] as $value_index => $value) {
if (!$value) {
unset($form_state['values']['submitted'][$value_index]);
}
}
}
$form_state['values']['details']['nid'] = $nid;
// Executing the pressed button action
drupal_build_form($form_id, $form_state);
return drupal_json_output(array(
'message' => t('Your submission has been received. Thank you for contacting us.'),
'status' => 'sent',
));
}
function _custom_webform_ajax_access() {
// TODO: Add user role / perm check
return true;
}
Чтобы пойти дальше, я бы хотел получить ошибки из обработанной формы, чтобы я мог отправить их обратно с помощью объекта json. Любые идеи ?
Скажите мне, если я ошибаюсь, но поскольку отправка веб-формы является узлом, почему бы не создать этот узел программно в вашем приложении
page callback
(с проверкой поля (или это можно сделать перед отправкой с использованием javascript))Это может быть что-то вроде
И вуаля ! :)
источник