Tôi đang làm việc trên một thực hiện Ajax cho Webform nộp trên Drupal 7. Tôi đã không thể tìm thấy bất kỳ tốt hook
để thay đổi nút Webform nộp và thêm '#ajax' theo hình thức do đó, tôi đã có một cái nhìn vào một mô-đun Drupal 6 mà thực hiện chức năng này từ một tập lệnh bên ngoài.
Vì vậy, tôi đã quyết định sử dụng mô-đun và mã JavaScript của riêng mình để gửi yêu cầu bài đăng Ajax tới một cuộc gọi lại menu tùy chỉnh mà tôi đã xác định trong hook_menu()
, trong Drupal 7.
Phần JavaScript hoạt động tốt nhưng tôi gặp sự cố khi gửi Webform theo chương trình.
Đây là mã JavaScript của tôi:
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
}
});
}
}
Và mã mô-đun của tôi (dựa trên mô-đun 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;
}
Khi tôi gửi biểu mẫu của mình, tôi nhận được 500 lỗi máy chủ.
Tôi đoán API biểu mẫu D6 & D7 khá khác nhau và tôi không chắc bắt đầu từ đâu để đoạn mã này hoạt động. Tôi đã cố gắng gỡ lỗi nhưng tôi không thể tìm ra cái gì tạo ra 500 lỗi.
Tôi sử dụng webform 3 và mô-đun tôi lấy mã cũng dựa trên phiên bản 3 của webform nhưng đối với Drupal 6. Nhưng cả hai mô-đun nên cung cấp cùng chức năng và cùng loại chức năng phía sau. Giải pháp đầu tiên: Nó có thể đến từ các giá trị tôi vượt qua sẽ không tương thích với api mẫu D7.
Trong nhật ký của tôi, tôi có:
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).
-- BIÊN TẬP --
Bây giờ tôi đang gỡ lỗi từng dòng, cuối cùng đoạn mã này có thể xứng đáng để trở thành mô-đun D7;)
Tôi đã tìm thấy trong tài liệu D7 rằng các đối số drupal numbuild_form () đã thay đổi từ D6 và $form_state
không thể để trống nữa ở giai đoạn này, vì vậy tôi đã cập nhật mã của mình theo cách này:
$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);
Bây giờ tôi đang cố gắng tìm tương đương với drupal_execute (), không còn tồn tại trong D7 nữa.
- Chỉnh sửa (2) -
Tôi đã làm cho nó hoạt động vài ngày trước và quay lại để chia sẻ giải pháp, và có thể nhận được một số lời khuyên và đề xuất cải tiến.
<?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;
}
Để tiến thêm một bước tôi muốn bây giờ nhận lỗi từ biểu mẫu đã xử lý để tôi có thể gửi lại với đối tượng json. Có ý kiến gì không?