Drupal → AJAX удаление товаров из корзины в Commerce 1

10.11.2013

Работающий, но проблемный код:

/**
 * Implements hook_form_FORM_ID_alter(): views_form_commerce_cart_form_default.
 */
function MODULENAME_form_views_form_commerce_cart_form_default_alter(&$form, &$form_state) {
  $form['#action'] = url('cart'); // Проблема 1
  if (!empty($form['edit_delete'])) {
    foreach(element_children($form['edit_delete']) as $key) {
      if (!empty($form['edit_delete'][$key]['#line_item_id'])) {
        $form['edit_delete'][$key]['#ajax'] = array(
          'callback' => 'MODULENAME_remove_ajax',
        );
      }
    }
  }
}

/**
 * "Remove" button ajax callback.
 */
function MODULENAME_remove_ajax($form, &$form_state) {
  drupal_get_messages();
  $_POST = array(); // Проблема 2
  $view = $form_state['build_info']['args'][0];
  $order_id = commerce_cart_order_id($GLOBALS['user']->uid);
  $cart_view_output = commerce_embed_view($view->name, $view->current_display, array($order_id));

  return array(
    '#type' => 'ajax',
    '#commands' => array(
      ajax_command_replace('.view-commerce-cart-form', $cart_view_output),
    ),
  );
}

Проблема 1: при обновлении всей формы через AJAX, у формы обнуляется #action и она всегда сабмитится на главную. Из-за этого приходится хардкодить $form['#action'] = url('cart');. Issue на drupal.org.

Проблема 2: при попытке отрендерить форму в ajax-callback этой же формы, форма пытается отправиться второй раз. Это особенность работы Form API. Поэтому перед рендерингом приходится очищать $_POST.

Доработанный и оформленный в виде рабочего модуля код можно забрать в моей песочнице — Commerce Ajax Cart Form.

Написанное актуально для
Commerce 1.x
Похожие записи

Комментарии

Проблема 1: Я думаю, надо посмотреть в сторону #limit_validation_errors.

с валидацией проблем нет, ошибок не возникает

А почему dc_cart_ajax не используете ?

Мне удалось найти еще одну тему касающуюся ajax и обсуждения dc_cart_ajax.

Вы не писали автору модуля по поводу кривости на drupal.org ?

Не могли бы вы здесь описать, что там сделано криво, хотя бы коротко ?

Если бы мы организовали сбор средств для разработки не кривого модуля,
во сколько бы вы оценили его ?

Стали бы вообще заниматься этим ?

Вам это под силу ?

Внутри view-commerce-cart-block кнопка удаления не работает.

Notice: Undefined index: #ajax in ajax_form_callback() (line 379 of includes\ajax.inc).

Вроде удалось переопределить и в блоке:

/**
 * Implements hook_form_FORM_ID_alter(): views_form_commerce_cart_form_default.
 */
function custommodule_form_views_form_commerce_cart_block_default_alter(&$form, &$form_state) {
  $form['#action'] = 'cart'; // Проблема 1
  if (!empty($form['edit_delete'])) {
    foreach(element_children($form['edit_delete']) as $key) {
      if (!empty($form['edit_delete'][$key]['#line_item_id'])) {
        $form['edit_delete'][$key]['#ajax'] = array('callback' => 'custommodule_remove_ajax');
      }
    }
  }
}

Проблема с использованием в блоке и форме одновременно.
По отдельности в форме или в блоке работает.
Либо #1, либо #2.
Если использовать вместе, то отваливаются модальные окна в ctools.
Вместо перехвата клика по ссылке ctools_link, происходит переход.

/**
 * "Remove" button ajax callback.
 */
function custommodule_remove_ajax($form, &$form_state) {
  drupal_get_messages();
  $_POST = array();
  $order_id = commerce_cart_order_id($GLOBALS['user']->uid);

  $cart_form = commerce_embed_view('commerce_cart_form', 'default', array($order_id));  // #1
  $cart_block = commerce_embed_view('commerce_cart_block', 'default', array($order_id)); // #2

//  Были попытки сделать как у groker в модуле:
//  $block = block_load('commerce_cart', 'cart');
//  $block_content = _block_render_blocks(array($block));
//  $build = _block_get_renderable_array($block_content);
//  $cart_block = drupal_render($build);

//  Есть мысль обновлять не весь блок целиком, а лишь часть "content".
//  $cart_block['content']

  $commands = array();
  $commands[] = ajax_command_replace('.view-commerce-cart-form', $cart_form);  // #1
  $commands[] = ajax_command_replace('.view-commerce-cart-block', $cart_block); // #2

  return array(
    '#type' => 'ajax',
    '#commands' => $commands
  );
}

Не хватает одного условия.
Подскажите пожалуйста, как правильно получить текущий адрес страницы находясь внутри MODULENAME_remove_ajax ?

Добавить комментарий