it-swarm.asia

كيفية إرسال نموذج ويب برمجيًا مع Ajax؟

أنا أعمل على تنفيذ Ajax لإرسال Webform في Drupal 7. لم أتمكن من العثور على أي hook جيد لتغيير زر إرسال Webform وإضافة '#ajax 'في النموذج لذلك ألقيت نظرة على وحدة دروبال 6 التي تنفذ هذه الوظيفة من برنامج نصي خارجي.

لذلك قررت أن أذهب مع الوحدة الخاصة بي ورمز جافا سكريبت لإطلاق طلب نشر Ajax إلى رد اتصال قائمة مخصص قمت بتحديده في hook_menu() ، في Drupal 7.

يعمل جزء جافا سكريبت بشكل جيد ولكن أواجه مشكلات في محاولة إرسال نموذج الويب برمجيًا.

هنا كود 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 خطأ في الخادم.

أعتقد أن واجهة برمجة تطبيقات نموذج D6 و D7 مختلفة تمامًا ولست متأكدًا من أين أبدأ في تشغيل هذه القطعة من التعليمات البرمجية. لقد حاولت تصحيحه ولكن لا يمكنني معرفة ما الذي يولد أخطاء 500.

أستخدم نموذج الويب 3 وتعتمد الوحدة التي أخذت الرمز عليها أيضًا على الإصدار 3 من نموذج الويب ولكن من أجل Drupal 6. ولكن يجب أن توفر كلتا الوحدتين الوظائف نفسها ونوع الوظائف خلفهما. الحل الأول : قد يأتي من القيم التي أمر بها والتي لن تكون متوافقة مع 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. أيه أفكار ؟

8
E. de Saint Chamas

كنت أفعل شيئًا مشابهًا ووجدت حل E. de Saint Chamas للعمل في الغالب بالنسبة لي. ومع ذلك ، كان هناك بعض الأشياء التي كنت بحاجة لإضافتها:

أولاً ، اضطررت إلى إضافة هذا إلى مصفوفة form_state قبل معالجة النموذج

'method' => 'post',

ثم ، في الجزء السفلي ، بعض التعديلات لمعالجة النموذج وإرجاع رسائل الخطأ إن وجدت:

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

لست متأكدًا مما إذا كانت هذه هي أفضل طريقة للقيام بذلك ، ولكن وجدت أنها نجحت معي. بالطبع ، قد ترغب في المضي قدمًا وتقديم رسائل الخطأ وإعادة مربع رسالة خطأ تم تقديمه بالكامل ، بالإضافة إلى ذلك ، يمكنك انتزاع "رسالة التأكيد" من الصفيف $ form_state بحيث يمكنك التحكم في رسالة النجاح من واجهة مستخدم نموذج الويب.

4
wesnick