Проверка формы AJAX и отправка

Я создал форму в Drupal 7 и хочу использовать AJAX. Я добавил это в массив кнопок отправки:

"#ajax" => array(
  "callback" => "my_callback",
  "wrapper" => "details-container",
  "effect" => "fade"
)

Это работает, но вся функция проверки игнорируется. Как я могу проверить форму до вызова my_callback()? И как я могу отображать статус или сообщения об ошибках в форме AJAX?


person Marius Ilie    schedule 26.10.2011    source источник
comment
Вы уверены, что проверка игнорируется? Я делал это десятки раз, и проверка никогда не игнорировалась (если только я специально не сказал Drupal игнорировать их, используя #limit_validation_errors). Кроме того, сообщения об ошибках автоматически загружаются в элемент wrapper по умолчанию, поэтому, как только вы исправите первый бит, он должен встать на место. Не могли бы вы опубликовать еще немного своего кода?   -  person Clive    schedule 26.10.2011
comment
@Clive Я только что сделал еще одну тестовую форму, те же результаты. Вот форма: function dr_search_test_form($form, &$fstate) { $form[wrapper] = array( #markup =› ‹div id='test-ajax'›‹/div› ); $form[name] = array( #type =› textfield, #required =› true, #title =› Name ); $form[submit] = array( #type =› submit, #value =› Send, #ajax =› array( callback =› dr_search_test_form_callback, wrapper =› test-ajax, effect =› fade ) ); вернуть $ форму; }   -  person Marius Ilie    schedule 27.10.2011
comment
функция dr_search_test_form_callback($form, &$fstate) { return sadsadas; } function dr_search_test_form_validate($form, &$fstate) { form_set_error(name, Some error to display.); }   -  person Marius Ilie    schedule 27.10.2011
comment
Я просто вижу текст из функции обратного вызова sadsadas, но проверка не происходит....   -  person Marius Ilie    schedule 27.10.2011


Ответы (6)


Этот вопрос и ответ помогли мне найти правильное решение, но оно не совсем кристально ясное. Сделаем так.

О чем нужно очень знать:

  1. Сообщения об ошибках проверки будут помещены внутрь всего, что указано как #ajax['wrapper']
  2. Обратите особое внимание на то, где находится документация по Drupal Forms API для ajax. обертка говорит, что "заменяется весь элемент с этим идентификатором, а не только содержимое элемента".
  3. Поскольку этот элемент заменяется, вам лучше предоставить его снова. Вот вот почему ответ Мариуса Илие работает - не из-за массива и #markup, а потому, что он включает div с установленным идентификатором оболочки.

Вот код, который работал у меня на основе того, что Мариус написал в комментарии выше:

function dr_search_test_form($form, &$fstate) {
  $form["wrapper"] = array("#markup" => "<div id='test-ajax'></div>");

  $form["name"] = array(
    "#type" => "textfield",
    "#required" => true,
    "#title" => "Name"
  );

  $form["submit"] = array(
    "#type" => "submit",
    "#value" => t("Send"),
    "#ajax" => array(
      "callback" => "dr_search_test_form_callback",
      "wrapper" => "test-ajax",
      "effect" => "fade",
    ),
  );
  return $form;
}

function dr_search_test_form_callback($form, &$fstate) {
  return "<div id='test-ajax'>Wrapper Div</div>";
}

function dr_search_test_form_validate($form, &$fstate) {
  form_set_error("name", "Some error to display.");
}
person Joshua Stewardson    schedule 28.06.2012
comment
+1 за то, что поделились своим опытом после закрытия вопроса; это настоящие вопросы и ответы сообщества. - person msanford; 17.09.2012
comment
Работает нормально. Как очистить значения формы после отправки? - person Rajesh Vishwakarma; 25.07.2019

Я нашел отличное решение этой проблемы.

Кредит идет в блог этого парня:

http://saw.tl/validate-form-ajax-submit-callback

Решение, которое он предлагает, следующее:

// when creating or altering the form..
{
  $form['#prefix'] = '<div id="formwrapper">';
  $form['#suffix'] = '</div>';
  // the submit button
  $form['save']['#ajax'] = array(
    'callback' => 'mymodule_form_ajax_submit',
    'wrapper' => 'formwrapper',
    'method' => 'replace',
    'effect' => 'fade',
  );
 // ...
}

function mymodule_from_ajax_submit($form, &$form_state) {
  // validate the form
  drupal_validate_form('mymodule_form_id', $form, $form_state);
  // if there are errors, return the form to display the error messages
  if (form_get_errors()) {
    $form_state['rebuild'] = TRUE;
    return $form;
  }
  // process the form
  mymodule_form_id_submit($form, $form_state);
  $output = array(
    '#markup' => 'Form submitted.'
  );
  // return the confirmation message
  return $output;
}
person bmunslow    schedule 06.03.2014
comment
$form['#prefix'] и $form['#suffix'] не работают в моем хуке _form_alter. - person AlxVallejo; 20.10.2014
comment
@AlxVallejo Это должно применяться к любому элементу формы, включая саму форму. Ознакомьтесь с Справочником по API форм - person bmunslow; 21.10.2014

Ничего из этого не работает для меня. Функция ajax отправки формы по-прежнему просто вызывает функцию обратного вызова напрямую, минуя проверку, отправку, а также делая так, чтобы кнопка не могла быть нажата несколько раз. Сообщения проверки НЕ отображаются. Я буквально скопировал и вставил код Джошуа Стюардсона, и это не сработало.

Тот факт, что этот вариант использования такой сложный и недокументированный, очень расстраивает. Мне кажется, что это самый простой запрос на API формы AJAX. Хорошо, я закончил изливать свое разочарование на решение.

Вот что я сделал, чтобы заставить это работать. Он чувствует себя хакерским и отсталым. Он также сломается, если на одной странице будет несколько экземпляров формы, но это было лучшее, что я мог сделать. Если кто-то может пролить свет на это, ПОЖАЛУЙСТА!

По сути, вам нужно заменить всю форму самой собой внутри вашего обратного вызова и вручную добавить любые установленные сообщения к объекту формы. Сделайте это, объявив оболочку идентификатором вашей формы (он сломается, если на одной странице есть несколько экземпляров вашей формы, потому что идентификатор будет обновлен).

function productsearchbar_savesearch_form($form, &$form_state) {

  $form["wrapper"] = array("#markup" => "<div class='inline-messages'></div>");

  $form["name"] = array(
    "#type" => "textfield", 
    "#required" => true,
    "#title" => "Name"
  );

  $form["submit"] = array(
    "#type" => "submit", 
    "#value" => "Send", 
    "#ajax" => array(
      "callback" => "productsearchbar_savesearch_form_callback", 
      "wrapper" => "productsearchbar-savesearch-form", 
      "effect" => "fade"
    )
  );

  return $form;
}

function productsearchbar_savesearch_form_callback($form, &$form_state) {
  $messages = theme('status_messages');

  if($messages){
    $form["wrapper"] = array("#markup" => "<div class='inline-messages'>$messages</div>");
  }
  return $form;
}

function productsearchbar_savesearch_form_validate($form, &$form_state) {
  if ($form_state['values']['name'] == '') {
   form_set_error('', t('Name field is empty!'));
  }
}

function productsearchbar_savesearch_form_submit($form, &$form_state) {
  drupal_set_message(t('Your form has been saved.'));
}
person Brent Hartmann    schedule 11.12.2012
comment
Я испытываю обратное: запускается обратный вызов Ajax, а затем вызывается функция отправки формы, и сообщение в обработчике отправки возвращается с ответом Ajax, в котором говорится, что он был сохранен. Это не то, чего я хочу. Так как это запускает пакетную операцию. Это Drupal 7, если это имеет значение. - person Elijah Lynn; 20.06.2016

Хорошо, я разбираюсь. По-видимому, вы должны вернуть массив в свою функцию обратного вызова ajax, а не только текстовое сообщение...

Что-то вроде этого:

return array("#markup" => "<div id='wrapper'></div>");
person Marius Ilie    schedule 27.10.2011

Я много часов искал способ сделать это правильно. К сожалению, большинство этих решений по-прежнему полагаются на проверку Drupal на стороне сервера, чтобы определить, следует ли помещать в оболочку результаты ajax или сообщения об ошибках на стороне клиента. Использование результатов сервера медленнее, чем проверка на стороне клиента, которая должна быть практически мгновенной. Кроме того, замена формы... формой... сообщениями об ошибках, на мой взгляд, слишком запутанна.

Используйте методы проверки jquery для запуска события ajax с помощью триггера javascript:

// Prevent form submission when there are client-side errors, trigger ajax event when it is valid
(function ($) {
    Drupal.behaviors.submitForm = { 
        attach: function (context) {
            var $form = $("form#validated_form", context);
            var $submitButton = $('input[type="submit"]', $form);

            $form
                .once('submitForm')
                .off('submit')
                .on('submit', function(e){

                    // Prevent normal form submission
                    e.preventDefault();
                    var $form = $(this);

                    // The trigger value should match what you have in your $form['submit'] array's ajax array
                    //if the form is valid, trigger the ajax event
                    if($form.valid()) {
                        $submitButton.trigger('submit_form');
                    }
            });

        }
    };
})(jQuery);

Ссылайтесь на триггер javascript как на прослушиваемое событие ajax:

$form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Submit'),
    '#ajax' => array(
      'event' => 'submit_form',
      'callback' => 'callback_function_for_when_form_is_valid',
      'wrapper' => 'validated_form'
    )
);

Теперь проверка запускается, как только нажимается кнопка отправки, а проверка на стороне сервера происходит только тогда, когда она действительна!

person CLL    schedule 13.01.2015

//вы можете использовать проверку формы jquery

jQuery('#button-id').mousedown(function() {
  var textval = $("#get-text-val").val();
  if (textval == '') {
    $("#apend-error-msg").append('<div id="add-text-error" class="add-text-error">error msg</div>');
   return false;
  }
  else {
    return true;
  }
  return false;
 });
person chathura    schedule 29.10.2013
comment
Выход за пределы Drupal для проверки может быть проблематичным, если вы хотите проверить не только длину строки. - person Kevin; 16.09.2014