Je travaille sur une implémentation Ajax pour la soumission Webform sur Drupal 7. Je n'ai pas pu trouver de bon hook
pour modifier le bouton de soumission Webform et ajouter '#ajax' dans le formulaire, j'ai donc jeté un œil à un module Drupal 6 qui implémente cette fonctionnalité à partir d'un script externe.
J'ai donc décidé d'aller avec mon propre module et mon code JavaScript pour lancer une demande de publication Ajax vers un rappel de menu personnalisé que j'ai défini dans hook_menu()
, dans Drupal 7.
La partie JavaScript fonctionne bien, mais je rencontre des problèmes pour envoyer le formulaire Web par programme.
Voici mon code 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
}
});
}
}
Et mon code de module (basé sur le module 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;
}
Lorsque je soumets mon formulaire, j'obtiens 500 erreurs de serveur.
Je suppose que les API de formulaire D6 et D7 sont assez différentes et je ne sais pas par où commencer pour que ce morceau de code fonctionne. J'ai essayé de le déboguer mais je n'arrive pas à comprendre ce qui génère les 500 erreurs.
J'utilise webform 3 et le module dont j'ai pris le code repose également sur la version 3 de webform mais pour Drupal 6. Mais les deux modules devraient fournir les mêmes fonctions et le même type de fonctionnalités derrière. Première solution de contournement: cela peut provenir des valeurs que je passe qui ne seraient pas compatibles avec l'api de forme D7.
Dans mon journal, j'ai:
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).
-- ÉDITER --
Je débogue ligne par ligne maintenant, à la fin ce morceau de code pourrait valoir la peine de devenir un module D7;)
J'ai trouvé dans la documentation D7 que les arguments drupal_rebuild_form () ont changé par rapport à D6, et que le $form_state
ne peut plus être vide à ce stade, j'ai donc mis à jour mon code de cette manière:
$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);
Maintenant, j'essaie de trouver l'équivalent de drupal_execute (), qui n'existe plus en D7.
- Modifier (2) -
Je l'ai fait fonctionner il y a quelques jours et je reviens pour partager la solution, et peut-être obtenir des conseils et des suggestions d'améliorations.
<?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;
}
Pour aller plus loin, je voudrais maintenant obtenir les erreurs du formulaire traité afin que je puisse les renvoyer avec l'objet json. Des idées ?
Dites-moi si je me trompe, mais comme une soumission de formulaire Web est un nœud, pourquoi ne pas créer directement le nœud par programmation dans votre
page callback
(avec validation de champ (ou pourrait le faire avant de soumettre en utilisant javascript))Cela pourrait être quelque chose comme
Et voilà ! :)
la source