Помогите с обратным вызовом ajax и drupal_process_form - PullRequest
2 голосов
/ 02 февраля 2010

У меня есть форма, которая добавляется через nodeapi, отображается только в режиме просмотра. Пользователи могут выбрать элемент из меню выбора, и их выбор будет автоматически сохранен в базе данных с обратным вызовом hook_menu при изменении. Если у пользователя отключен javascript, он будет отправляться в обычном формате api. Все это работает нормально, но теперь из соображений безопасности я хочу отправить версию ajax через форму api. Мой form_name_submit прост как:

function mymodule_test_form_submit($form, &$form_state) {
  global $user;
  db_query("INSERT INTO {mymodule} (nid, uid, status, created) VALUES (%d, %d, %d, " . time() . ")", $form['#parameters'][2], $user->uid, $form_state['values']['mymodule_status']);
}

Мой Аякс:

$('.mysubmit').css('display', 'none');
$('.myclass').change(function() {
  $.ajax({
    type: 'POST',
    url: Drupal.settings.basePath + 'mymodule/set/' + $nid + '/' + $('.myclass').val(),
    dataType: 'json',
    data: { 'ajax' : true, 'form_build_id' : $('#mymodule-form input[name=form_build_id]').val() }
  });
});

И моя функция обратного вызова:

function mymodule_set($nid, $status) {
  $form_build_id = $_POST['form_build_id'];
  $form_state = array('storage' => NULL, 'submitted' => FALSE);
  $form = form_get_cache($form_build_id, $form_state);
  $args = $form['#parameters'];
  $form_id = array_shift($args);
  $form['#post'] = $_POST;
  $form['#redirect'] = FALSE;
  $form['#programmed'] = FALSE;
  $form_state['post'] = $_POST;
  drupal_process_form($form_id, $form, $form_state);
}

Первоначально моя функция обратного вызова была примерно такой же, как моя функция отправки, но теперь я пытаюсь использовать функцию отправки и с ajax. Это правильный способ использовать drupal_process_form? Форма извлекается из кеша, проверяется и отправляется, если нет ошибок? Я использую некоторый код из этого учебника, чтобы применить его к моей ситуации: http://drupal.org/node/331941 Кажется, нет никаких примеров того, что я пытаюсь сделать. У меня также есть $ form ['# cache'] = TRUE; в моей форме функции.

Как drupal_process_form сравнивает отправленные значения с исходной формой для проверки целостности? Я должен добавить свои значения в form_state, так как состояние формы будет пустым с ajax. Застрял на этом в течение нескольких дней, надеюсь, кто-то имеет опыт с этим.

Спасибо.

1 Ответ

1 голос
/ 05 февраля 2010

В прошлом мне приходилось делать схожий с тобой аналог и читать тот же учебник, который ты выложил, к сожалению, по этому поводу не так много информации, и мне было очень трудно заставить его работать. Я не очень хорошо помню детали, но я посмотрел на код, который я написал, и вот несколько советов, которые могут работать для вас:

  • Не отправляйте форму, используя свой собственный код jQuery, вместо этого используйте новое свойство "#ahah" элементов формы, которое можно использовать для вызова вашего обратного вызова при замене select http://api.drupal.org/api/drupal/developer--topics--forms_api_reference.html/6#ahah

Если вы делаете это в форме узла, добавление свойства #ahah в форму может измениться, я помню, что видел проблему, которая не была решена в тот момент. если это так, используйте этот код для присоединения привязки ahah, вам не понадобятся «efect», «method» или «progress», поскольку вы просто хотите отправить форму, чтобы ничего не менять в ней:

function YOURMODULE_form_alter(&$form, $form_state, $form_id) {
  if ('YOURCONTENTTYPE_node_form' == $form_id) {
    //the only way I could make it work for exisiting fields is adding the binding "manually"
    $ahah_binding = array(
      'url'   => url('YOURCALLBACKPATH'), 
      'event' => 'change',
      'wrapper' => 'FIELD-wrapper',
      'selector' => '#FIELD',
      'effect'   => 'fade',
      'method'   => 'replace',
      'progress' => array('type' => 'throbber'),
    );

    drupal_add_js('misc/jquery.form.js');
    drupal_add_js('misc/ahah.js');
    drupal_add_js(array('ahah' => array('FIELDd' => $ahah_binding)), 'setting');

    //force the form to be cached
    $form['#cache'] = TRUE;
  }
}
  • Вот моя функция обратного вызова, обратите внимание, что она имеет некоторые модификации из учебника, который вы опубликовали:

    function YOURMODULE_js() {
    
      // The form is generated in an include file which we need to include manually.
      include_once 'modules/node/node.pages.inc';
      // We're starting in step #3, preparing for #4.
      //I have to add the 'rebuild' element, if not an empty node was created
      $form_state = array('storage' => NULL, 'submitted' => FALSE, 'rebuild' => TRUE);
      $form_build_id = $_POST['form_build_id'];
      // Step #4.
      $form = form_get_cache($form_build_id, $form_state);
    
      // Preparing for #5.
      $args = $form['#parameters'];
      $form_id = array_shift($args);
      $form_state['post'] = $form['#post'] = $_POST;
      $form['#programmed'] = $form['#redirect'] = FALSE;
    
      // if you want to do any modification to the form values, this is the place 
    
      // Step #5.
      drupal_process_form($form_id, $form, $form_state);
      // Step #6 and #7 and #8.
      $form = drupal_rebuild_form($form_id, $form_state, $args, $form_build_id);
    
    
      // Final rendering callback.
      drupal_json(array('status' => TRUE, 'data' => $output));
    }
    

Как я уже говорил, есть детали, которые я забыл, но, возможно, это поможет вам.

Удачи.

...