Ajax ile web formu programlı olarak nasıl gönderilir?


8

Ben Drupal 7. I göndermek web formu için bir Ajax uygulaması üzerinde çalışıyorum hiçbir işe bulmak mümkün değildi hookben bir bir göz vardı Webform gönder düğmesi ve formda '#ajax' eklemek değiştirmek için Drupal 6 modül o bu işlevi harici bir komut dosyasından uygular.

Bu yüzden hook_menu()Drupal 7'de tanımladığım özel bir menü geri aramasına Ajax posta isteği göndermek için kendi modülüm ve JavaScript kodumla gitmeye karar verdim .

JavaScript bölümü iyi çalışıyor ancak Web formunu programlı olarak göndermeye çalışırken sorun yaşıyorum.

İşte JavaScript kodum:

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

Ve modül kodum (webform_ajax modülüne dayanarak):

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

Formumu gönderdiğimde 500 sunucu hatası alıyorum.

Sanırım D6 ve D7 form API oldukça farklı ve bu kod parçası çalışmaya başlamak için nereden emin değilim. Hata ayıklamaya çalıştım, ancak 500 hatalarının ne olduğunu anlayamıyorum.

Webform 3 kullanıyorum ve kodu aldığım modül de webform 3 sürümüne dayanıyor, ancak Drupal 6 için. Ama her iki modül de aynı işlevleri ve aynı tür işlevleri sağlamalıdır. İlk geçici çözüm: D7 form api ile uyumlu olmayan geçirdiğim i değerlerinden gelebilir.

Günlüğümde:

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

-- DÜZENLE --

Şimdi satır satır hata ayıklama, sonunda bu kod parçası bir D7 modülü olmaya değer olabilir;)

D7 belgelerinde drupal_rebuild_form () argümanlarının D6'dan değiştiğini ve $form_statebu aşamada artık boş olamayacağını buldum, bu yüzden kodumu bu şekilde güncelledim:

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

Şimdi d7 artık var drupal_execute (), eşdeğerini bulmaya çalışıyorum.

- Düzenle (2) -

Birkaç gün önce çalıştım ve çözümü paylaşmak için geri geldim ve belki bazı öneriler ve iyileştirme önerileri alıyorum.

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

Bir adım daha ileri gitmek için şimdi json nesnesi ile geri gönderebilir böylece işlenmiş formdaki hataları almak istiyorum. Herhangi bir fikir ?

Yanıtlar:


4

Benzer bir şey yapıyordum ve çoğunlukla benim için çalışmak için E. de Saint Chamas'ın çözümünü buldum. Ancak, eklemem gereken birkaç şey vardı:

İlk olarak, formu işlemeden önce form_state dizisine eklemek zorunda kaldım

'method' => 'post',

Ardından, aşağıya doğru, formu işlemek ve varsa hata iletilerini döndürmek için bazı ayarlamalar:

  // 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'],
  ));

Bunun en iyi yolu olup olmadığından emin değilim, ama benim için işe yaradı. Tabii ki, sadece devam edip hata mesajlarını oluşturmak ve tamamen işlenmiş bir hata mesajı kutusu döndürmek isteyebilirsiniz ve ek olarak, $ form_state dizisinden "onay mesajını" koparabilirsiniz, böylece başarı mesajını webformu kullanıcı arayüzü.


Bu harika, ama bir hata almaya devam ediyorum ($ form_state ['executive'] = False). Ve drupal_get_messages hiçbir şey ('hata'). Bunu nasıl ayıklayabileceğimi merak ediyorum.
cybertoast

Ben curl ile göndermeye çalışıyorum, curl -vvv -X POST -H "X-İstenen-ile: XMLHttpRequest" -d 'gönderilen [contact_fullname] = benim% 20name & gönderilen [contact_email] = test% 40example. com.tr ve gönderilen [contact_message] =% 20message '" localhost / fubar / 31 " test edildi . İçerik gönderilir ve form_state doldurulur, ancak drupal_form_build () çalıştırılmaz / gönderilmez.
cybertoast

-1

Yanlış olduğumu söyle, ancak bir web formu gönderimi bir düğüm olduğu için, düğümü neden doğrudan programınızda oluşturmuyorsunuz page callback(alan doğrulamasıyla (veya javascript kullanarak göndermeden önce yapabilir))

Gibi bir şey olabilir

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;

Et voilà! :)


3
Aslında web formu gönderimleri düğüm değildir. Webform, gönderimleri kendi tablolarında saklar. Dolayısıyla, gönderimi eklemek için yeni bir düğüm oluşturulamaz. Ayrıca, form çalıştırıldıktan sonra tüm webform doğrulama iş akışının tetiklenmesini istiyorum, böylece gerekli alanları vb.
Kontrol eder
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.