Bagaimana cara mengirimkan formulir web secara terprogram dengan Ajax?


8

Saya sedang mengerjakan implementasi Ajax untuk pengiriman Webform pada Drupal 7. Saya tidak dapat menemukan yang baik hookuntuk mengubah tombol pengiriman Webform dan menambahkan '#ajax' di formulir jadi saya melihat-lihat modul Drupal 6 yang mengimplementasikan fungsi ini dari skrip eksternal.

Jadi saya memutuskan untuk pergi dengan modul saya sendiri dan kode JavaScript untuk mem-posting permintaan posting Ajax ke callback menu kustom yang telah saya definisikan di hook_menu(), dalam Drupal 7.

Bagian JavaScript berfungsi dengan baik tetapi saya mengalami masalah saat mencoba mengirimkan Webform secara terprogram.

Ini kode JavaScript saya:

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
      }
    });
  }
}

Dan kode modul saya (berdasarkan modul 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;
}

Ketika saya mengirimkan formulir saya, saya mendapatkan 500 kesalahan server.

Saya kira API bentuk D6 & D7 sangat berbeda dan saya tidak yakin harus mulai dari mana kode ini bekerja. Saya telah mencoba untuk debug tetapi saya tidak tahu apa yang menghasilkan 500 kesalahan.

Saya menggunakan webform 3 dan modul saya mengambil kode juga bergantung pada versi 3 dari webform tetapi untuk Drupal 6. Tetapi kedua modul harus menyediakan fungsi yang sama dan jenis fungsi yang sama di belakang. Solusi pertama: Mungkin berasal dari nilai yang saya lewati yang tidak akan kompatibel dengan D7 dari api.

Dalam log saya, saya punya:

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).

- EDIT -

Saya sedang men-debug baris demi baris sekarang, pada akhirnya bagian kode ini dapat menjadi modul D7;)

Saya menemukan dalam dokumentasi D7 bahwa argumen drupal_rebuild_form () telah berubah dari D6, dan bahwa argumen $form_statetidak dapat kosong lagi pada tahap ini, jadi saya memperbarui kode saya dengan cara ini:

$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);

Sekarang saya mencoba untuk menemukan yang setara dengan drupal_execute (), yang tidak ada lagi di D7.

- Edit (2) -

Saya berhasil beberapa hari yang lalu dan kembali untuk berbagi solusi, dan mungkin mendapatkan beberapa saran dan saran perbaikan.

<?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;
}

Untuk melangkah lebih jauh, saya ingin sekarang mendapatkan kesalahan dari formulir yang diproses sehingga saya bisa mengirimnya kembali dengan objek json. Ada ide?

Jawaban:


4

Saya melakukan sesuatu yang serupa dan menemukan solusi E. de Saint Chamas untuk sebagian besar bekerja untuk saya. Namun, ada beberapa hal yang perlu saya tambahkan:

Pertama, saya harus menambahkan ini ke form_state array sebelum memproses formulir

'method' => 'post',

Kemudian, di bagian bawah, beberapa penyesuaian untuk memproses formulir dan mengembalikan pesan kesalahan jika ada:

  // Prevent the form from redirecting the request
  $form_state['no_redirect'] = TRUE;
  // Executing the pressed button action
  drupal_build_form($form_id, $form_state);
  // See if the form submitted successfully
  if (!$form_state['executed']) {
    // If the form didn't submit successfully, get the errors
    // which are set bu drupal_set_message
    $messages = drupal_get_messages('error');
    $messages = implode('<br />', $messages['error']);
  }
  else {
    // If form submitted successfully, create a nice message.
    $messages = "Thanks for contacting us! We will let you know when the Beta is live!";
  }
  // drupal_json_output seems to confuse some browsers, who want to save as a file 
  print drupal_json_encode(array(
    'message' => $messages,
    'status' => $form_state['executed'],
  ));

Saya tidak yakin apakah ini cara terbaik untuk melakukannya, tetapi ternyata ini berhasil untuk saya. Tentu saja, Anda mungkin ingin langsung melanjutkan dan merender pesan kesalahan dan mengembalikan kotak pesan kesalahan yang sepenuhnya diberikan, dan selain itu, Anda bisa memetik "pesan konfirmasi" dari array $ form_state sehingga Anda dapat mengontrol pesan sukses dari UI formulir web.


Ini bagus, tetapi saya terus mengalami kegagalan ($ form_state ['dieksekusi'] = Salah). Dan tidak ada di drupal_get_messages ('error'). Bertanya-tanya bagaimana saya bisa men-debug ini.
cybertoast

Saya harus mengklarifikasi bahwa saya mencoba mengirimkan melalui curl, seperti curl -vvv -X POST -H "X-Diminta-Dengan: XMLHttpRequest" -d 'terkirim [contact_fullname] = my% 20name & dikirimkan [contact_email] = test% 40example. com & dikirimkan [contact_message] = test% 20message '" localhost / fubar / 31 ". Konten dikirim dan form_state diisi, tetapi drupal_form_build () tidak dieksekusi / dikirimkan.
cybertoast

-1

Beri tahu saya jika saya salah tetapi karena pengiriman formulir web adalah simpul, mengapa tidak membuat simpul secara langsung di dalam program Anda page callback(dengan validasi bidang (atau dapat dilakukan sebelum mengirim menggunakan javascript))

Bisa jadi sesuatu seperti

if(!function_exists("node_object_prepare"))
{
  include_once(drupal_get_path('module', 'node') . '/node.pages.inc');
}
$node = new stdClass();                                                         
$node->is_new = TRUE;
$node->type = 'YOUR_NODE_TYPE_HERE';                                
node_object_prepare($node);

// then all the fields you need

node_validate($node);
$node = node_submit($node);
node_save($node);
$nid = $node->nid;

Dan lagi! :)


3
Sebenarnya pengiriman formulir web bukan simpul. Webform menyimpan kiriman di tabelnya sendiri. Jadi kami tidak dapat membuat simpul baru yang dibuat untuk menambahkan kiriman. Selain itu saya ingin memiliki seluruh alur kerja validasi formulir web dipicu setelah formulir dieksekusi sehingga memeriksa bidang yang diperlukan, dll ...
E. de Saint Chamas
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.