프로그래밍 방식으로 Ajax로 웹 양식을 제출하는 방법은 무엇입니까?


8

Drupal 7에서 Webform 제출을 위해 Ajax 구현을 작업 중입니다 hook. Webform 제출 버튼을 변경하고 양식에 '#ajax'를 추가하여 Drupal 6 모듈 을 살펴볼 수있는 좋은 점 을 찾을 수 없었습니다. 외부 스크립트에서이 기능을 구현합니다.

그래서 hook_menu()Drupal 7에서 정의한 사용자 정의 메뉴 콜백에 Ajax 게시 요청을 실행하기 위해 자체 모듈 및 JavaScript 코드를 사용하기로 결정했습니다 .

JavaScript 부분은 정상적으로 작동하지만 프로그래밍 방식으로 웹 양식을 제출하는 데 문제가 있습니다.

내 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 양식 API가 상당히 다르고이 코드를 작동시킬 위치를 잘 모르겠습니다. 디버깅을 시도했지만 500 오류가 발생하는 원인을 알 수 없습니다.

나는 webform 3을 사용하고 코드를 취한 모듈은 webform의 버전 3에 의존하지만 Drupal 6에 의존합니다. 그러나 두 모듈 모두 동일한 기능과 동일한 종류의 기능을 제공해야합니다. 첫 번째 해결 방법 : D7 양식 API와 호환되지 않는 값을 전달할 수 있습니다.

내 로그에 나는 가지고있다 :

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

이제 D7에 더 이상 존재하지 않는 drupal_execute ()와 동등한 것을 찾으려고합니다.

-편집 (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 객체와 함께 다시 보낼 수 있습니다. 어떤 아이디어?

답변:


4

나는 비슷한 일을하고 있었고 대부분 나를 위해 일하는 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 배열에서 "확인 메시지"를 뽑아서 성공 메시지를 제어 할 수 있습니다. 웹 양식 UI.


이것은 훌륭하지만 계속 실패합니다 ($ form_state [ 'executed'] = False). 그리고 drupal_get_messages ( 'error')에는 아무것도 없습니다. 어떻게 디버깅 할 수 있는지 궁금합니다.
cybertoast

curl -vvv -X POST -H "X-Requested-With : XMLHttpRequest"-d 'submitted [contact_fullname] = my % 20name & submitted [contact_email] = test % 40example과 같이 curl을 통해 제출하려고합니다. com & submitted [contact_message] = test % 20message ' " localhost / fubar / 31 "입니다. 내용이 전송되고 form_state가 채워지지만 drupal_form_build ()는 실행 / 제출되지 않습니다.
cybertoast

-1

내가 틀렸지 만 웹 양식 제출이 노드이기 때문에 알려주십시오 page callback(필드 유효성 검사를 사용하여 (또는 자바 스크립트를 사용하여 제출하기 전에 수행 할 수 있음))

그것은 같은 것일 수 있습니다

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;

vo! :)


3
실제로 웹 양식 제출은 노드가 아닙니다. Webform은 자체 테이블에 제출을 저장합니다. 따라서 제출을 추가하기 위해 새 노드를 만들 수 없습니다. 또한 양식이 실행되면 전체 웹 양식 유효성 검사 워크 플로가 트리거되어 필요한 필드 등을 검사하고
싶습니다
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.