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

#jquery #ajax #drupal-7 #drupal-forms

#jquery #ajax #drupal-7 #drupal-forms

Вопрос:

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

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

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

Комментарии:

1. Вы уверены, что проверка игнорируется? Я делал это десятки раз, и проверка никогда не игнорировалась (если я специально не сказал Drupal игнорировать их использование #limit_validation_errors ). Также сообщения об ошибках автоматически загружаются в wrapper элемент по умолчанию, поэтому, как только вы исправите первый бит, он должен просто встать на свое место. Не могли бы вы опубликовать еще немного своего кода?

2. @Clive Я только что создал другую тестовую форму, те же результаты. Вот форма: функция dr_search_test_form($form, amp;$fstate) { $form[«wrapper»] = array( «#markup» => «<div id=’test-ajax’></div>» ); $form[«name»] = array(«#type» => «textfield», «#required» => true, «#title» => «Name» ); $form[«submit»] = массив ( «#type» => «submit», «#value» => «Отправить», «#ajax» => array( «обратный вызов» => «dr_search_test_form_callback», «оболочка» => «тест-ajax», «эффект» => «fade» ) ); возвращает $form; }

3. функция dr_search_test_form_callback($form, amp;$fstate) { возвращает «sadsadas»; } функция dr_search_test_form_validate($form, amp;$fstate) { form_set_error(«имя», «Отображается некоторая ошибка».); }

4. Я просто вижу текст из функции обратного вызова «sadsadas», но проверка не выполняется….

Ответ №1:

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

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

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

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

 function dr_search_test_form($form, amp;$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, amp;$fstate) {
  return "<div id='test-ajax'>Wrapper Div</div>";
}

function dr_search_test_form_validate($form, amp;$fstate) {
  form_set_error("name", "Some error to display.");
}
  

Комментарии:

1. 1 за то, что поделился своим опытом после закрытия вопроса; это настоящие вопросы и ответы сообщества.

2. Работает нормально. Как очистить значения формы после отправки?

Ответ №2:

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

Заслуга принадлежит блогу этого парня:

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, amp;$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;
}
  

Комментарии:

1. $form[‘#prefix’] и $form[‘#suffix’] не работают в моем перехватчике _form_alter.

2. @AlxVallejo Это должно применяться к любому элементу формы, включая саму форму. Проверьте ссылку на API формы

Ответ №3:

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

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

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

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

 function productsearchbar_savesearch_form($form, amp;$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, amp;$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, amp;$form_state) {
  if ($form_state['values']['name'] == '') {
   form_set_error('', t('Name field is empty!'));
  }
}

function productsearchbar_savesearch_form_submit($form, amp;$form_state) {
  drupal_set_message(t('Your form has been saved.'));
}
  

Комментарии:

1. Я испытываю обратное, запускается обратный вызов Ajax, а затем вызывается функция отправки формы, и сообщение в обработчике отправки возвращается с ответом Ajax, в котором говорится, что оно было сохранено. Это не то, чего я хочу. Поскольку это запускает пакетную операцию. Это Drupal 7, если это имеет значение.

Ответ №4:

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

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

 return array("#markup" => "<div id='wrapper'></div>");
  

Ответ №5:

Я много часов искал способ сделать это правильно. К сожалению, большинство этих решений по-прежнему полагаются на проверку на стороне сервера 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'
    )
);
  

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

Ответ №6:

// вы можете использовать проверку формы 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;
 });
  

Комментарии:

1. Выход за пределы Drupal для проверки может быть проблематичным, если вы хотите проверить больше, чем длину строки.