Loading README.md +2 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ INTRODUCTION ------------ When a user changes items quantity in Cart popup, this module refreshes total sums w/o refreshing a page. In Cart popup outputs currency symbol, not it's code. REQUIREMENTS Loading @@ -33,6 +34,7 @@ Add block "Commerce ajax cart block" Install my fork of module dc_ajax_add_cart from install igrowl from add libraries unpack animate.tar and igrowl.tar from module dc_ajax_add_cart to /libraries add edit price field at view commerce_products To customize cart block markup see commerce_ajax/templates/commerce-ajax-cart-block.html.twig Loading commerce_ajax.module +8 −63 Original line number Diff line number Diff line <?php function commerce_ajax_update_cart($form, \Drupal\Core\Form\FormStateInterface $form_state) { $triggering_element = $form_state->getTriggeringElement(); $order_id = $triggering_element['#order_id']; $view = reset($form_state->getBuildInfo()['args']); $quantities = $form_state->getValue('edit_quantity', []); $order = \Drupal::entityTypeManager()->getStorage('commerce_order')->load($order_id); $cartManager = \Drupal::service('commerce_cart.cart_manager'); foreach ($quantities as $row_index => $quantity) { /** @var \Drupal\commerce_order\Entity\OrderItemInterface $order_item */ $order_item = $view->result[$row_index]->_relationship_entities['order_items']; if ($order_item->getQuantity() != $quantity) { $order_item->setQuantity($quantity); $order = $order_item->getOrder(); $cartManager->updateOrderItem($order, $order_item, FALSE); // Tells commerce_cart_order_item_views_form_submit() to save the order. $form_state->set('quantity_updated', TRUE); $form_state->setValue(['edit_quantity', $row_index], $quantity); // $form['edit_quantity'][$row_index]['#value'] } } /** @var \Drupal\commerce_order\Entity\OrderInterface $order */ $order->save(); return $form; // return Drupal::service('commerce_ajax.refresh_page_elements_helper') // ->updatePageElements($form) // ->getResponse(); } /** * Implements hook_form_alter(). * Implements hook_views_data_alter(). */ function commerce_ajax_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) { if ($form_state->getFormObject() instanceof \Drupal\views\Form\ViewsForm) { /** @var \Drupal\views\ViewExecutable $view */ $view = reset($form_state->getBuildInfo()['args']); $tag = $view->storage->get('tag'); $view_has_content = !empty($view->result); if ($tag == 'commerce_cart_block' && $view_has_content) { foreach ($form['edit_quantity'] as $key => $v) { if(is_int($key)) { $form['edit_quantity'][$key]['#ajax'] = [ 'callback' => 'commerce_ajax_update_cart', 'wrapper' => 'commerce_cart_block-cart-ajax-wrapper', 'event' => 'change', function commerce_ajax_views_data_alter(array &$data) { $data['commerce_product_variation']['edit_price']['field'] = [ 'title' => t('Price text field'), 'help' => t('Adds a text field for editing the price.'), 'id' => 'commerce_ajax_edit_price', ]; $form['edit_quantity'][$key]['#order_id'] = $view->argument['order_id']->value[0]; } } foreach ($form['remove_button'] as $key => $v) { if(is_int($key)) { // $form['remove_button'][$key]['#ajax'] = [ // 'callback' => 'commerce_ajax_update_cart', // 'wrapper' => 'commerce_cart_block-cart-ajax-wrapper', // ]; // $form['remove_button'][$key]['#attributes'] = [ // 'class' => ['use-ajax-submit'], // ]; // $form['remove_button'][$key]['#order_id'] = $view->argument['order_id']->value[0]; } } $form['#prefix'] = '<div id="commerce_cart_block-cart-ajax-wrapper"><div class="views-form">'; $form['#suffix'] = '</div></div>'; } } } /** Loading commerce_ajax.schema.yml 0 → 100644 +2 −0 Original line number Diff line number Diff line views.field.commerce_ajax_edit_price: type: views.field.field css/commerce_ajax.theme.css +0 −1 Original line number Diff line number Diff line Loading @@ -219,7 +219,6 @@ width: 42px; height: 42px; background: #b7b7b7; margin: 0.8em 0 0; border-radius: 50%; border: none; position: relative; } Loading src/Plugin/views/field/EditPrice.php 0 → 100644 +141 −0 Original line number Diff line number Diff line <?php namespace Drupal\commerce_ajax\Plugin\views\field; use Drupal\Core\Form\FormStateInterface; use Drupal\views\Plugin\views\field\FieldPluginBase; use Drupal\views\Plugin\views\field\UncacheableFieldHandlerTrait; use Drupal\views\ResultRow; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Defines a form element for editing the order item quantity. * * @ViewsField("commerce_ajax_edit_price") */ class EditPrice extends FieldPluginBase { use UncacheableFieldHandlerTrait; /** * Constructs a new EditPrice object. * * @param array $configuration * A configuration array containing information about the plugin instance. * @param string $plugin_id * The plugin ID for the plugin instance. * @param mixed $plugin_definition * The plugin implementation definition. */ public function __construct(array $configuration, $plugin_id, $plugin_definition) { parent::__construct($configuration, $plugin_id, $plugin_definition); } /** * {@inheritdoc} */ public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { return new static( $configuration, $plugin_id, $plugin_definition ); } /** * {@inheritdoc} */ public function clickSortable() { return FALSE; } /** * {@inheritdoc} */ protected function defineOptions() { $options = parent::defineOptions(); return $options; } /** * {@inheritdoc} */ public function buildOptionsForm(&$form, FormStateInterface $form_state) { parent::buildOptionsForm($form, $form_state); } /** * {@inheritdoc} */ public function getValue(ResultRow $row, $field = NULL) { return '<!--form-item-' . $this->options['id'] . '--' . $row->index . '-->'; } /** * Form constructor for the views form. * * @param array $form * An associative array containing the structure of the form. * @param \Drupal\Core\Form\FormStateInterface $form_state * The current state of the form. */ public function viewsForm(array &$form, FormStateInterface $form_state) { // Make sure we do not accidentally cache this form. $form['#cache']['max-age'] = 0; // The view is empty, abort. if (empty($this->view->result)) { return; } $form[$this->options['id']]['#tree'] = TRUE; foreach ($this->view->result as $row_index => $row) { /** @var \Drupal\commerce_product\Entity\ProductVariationInterface $product_variation */ $product_variation = $this->getEntity($row); $form[$this->options['id']][$row_index] = [ '#type' => 'textfield', '#title' => $this->t('Price'), '#title_display' => 'invisible', '#default_value' => number_format($product_variation->getPrice()->getNumber(), 2, '.', ''), '#size' => 9, '#ajax' => [ 'callback' => 'Drupal\commerce_ajax\Plugin\views\field\EditPrice::viewsFormSubmit', 'wrapper' => '#not-exist-element', 'event' => 'change', ], '#suffix' => '<span class="currency">'.$product_variation->getPrice()->getCurrencyCode().'</span>', ]; } } /** * Submit handler for the views form. * * @param array $form * An associative array containing the structure of the form. * @param \Drupal\Core\Form\FormStateInterface $form_state * The current state of the form. */ public function viewsFormSubmit(array &$form, FormStateInterface $form_state) { $triggering_element = $form_state->getTriggeringElement(); $view = reset($form_state->getBuildInfo()['args']); $price_list = $form_state->getValue($triggering_element['#parents'][0], []); foreach ($price_list as $row_index => $price) { /** @var \Drupal\commerce_product\Entity\ProductVariationInterface $product_variation */ $view_result = $view->result[$row_index]; $product_variation = $view_result->_relationship_entities['variations']; if ($product_variation->getPrice()->getNumber() != $price) { $product_variation->setPrice(new \Drupal\commerce_price\Price($price, $product_variation->getPrice()->getCurrencyCode())); $product_variation->save(); } } return []; } /** * {@inheritdoc} */ public function query() { // Do nothing. } } Loading
README.md +2 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ INTRODUCTION ------------ When a user changes items quantity in Cart popup, this module refreshes total sums w/o refreshing a page. In Cart popup outputs currency symbol, not it's code. REQUIREMENTS Loading @@ -33,6 +34,7 @@ Add block "Commerce ajax cart block" Install my fork of module dc_ajax_add_cart from install igrowl from add libraries unpack animate.tar and igrowl.tar from module dc_ajax_add_cart to /libraries add edit price field at view commerce_products To customize cart block markup see commerce_ajax/templates/commerce-ajax-cart-block.html.twig Loading
commerce_ajax.module +8 −63 Original line number Diff line number Diff line <?php function commerce_ajax_update_cart($form, \Drupal\Core\Form\FormStateInterface $form_state) { $triggering_element = $form_state->getTriggeringElement(); $order_id = $triggering_element['#order_id']; $view = reset($form_state->getBuildInfo()['args']); $quantities = $form_state->getValue('edit_quantity', []); $order = \Drupal::entityTypeManager()->getStorage('commerce_order')->load($order_id); $cartManager = \Drupal::service('commerce_cart.cart_manager'); foreach ($quantities as $row_index => $quantity) { /** @var \Drupal\commerce_order\Entity\OrderItemInterface $order_item */ $order_item = $view->result[$row_index]->_relationship_entities['order_items']; if ($order_item->getQuantity() != $quantity) { $order_item->setQuantity($quantity); $order = $order_item->getOrder(); $cartManager->updateOrderItem($order, $order_item, FALSE); // Tells commerce_cart_order_item_views_form_submit() to save the order. $form_state->set('quantity_updated', TRUE); $form_state->setValue(['edit_quantity', $row_index], $quantity); // $form['edit_quantity'][$row_index]['#value'] } } /** @var \Drupal\commerce_order\Entity\OrderInterface $order */ $order->save(); return $form; // return Drupal::service('commerce_ajax.refresh_page_elements_helper') // ->updatePageElements($form) // ->getResponse(); } /** * Implements hook_form_alter(). * Implements hook_views_data_alter(). */ function commerce_ajax_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) { if ($form_state->getFormObject() instanceof \Drupal\views\Form\ViewsForm) { /** @var \Drupal\views\ViewExecutable $view */ $view = reset($form_state->getBuildInfo()['args']); $tag = $view->storage->get('tag'); $view_has_content = !empty($view->result); if ($tag == 'commerce_cart_block' && $view_has_content) { foreach ($form['edit_quantity'] as $key => $v) { if(is_int($key)) { $form['edit_quantity'][$key]['#ajax'] = [ 'callback' => 'commerce_ajax_update_cart', 'wrapper' => 'commerce_cart_block-cart-ajax-wrapper', 'event' => 'change', function commerce_ajax_views_data_alter(array &$data) { $data['commerce_product_variation']['edit_price']['field'] = [ 'title' => t('Price text field'), 'help' => t('Adds a text field for editing the price.'), 'id' => 'commerce_ajax_edit_price', ]; $form['edit_quantity'][$key]['#order_id'] = $view->argument['order_id']->value[0]; } } foreach ($form['remove_button'] as $key => $v) { if(is_int($key)) { // $form['remove_button'][$key]['#ajax'] = [ // 'callback' => 'commerce_ajax_update_cart', // 'wrapper' => 'commerce_cart_block-cart-ajax-wrapper', // ]; // $form['remove_button'][$key]['#attributes'] = [ // 'class' => ['use-ajax-submit'], // ]; // $form['remove_button'][$key]['#order_id'] = $view->argument['order_id']->value[0]; } } $form['#prefix'] = '<div id="commerce_cart_block-cart-ajax-wrapper"><div class="views-form">'; $form['#suffix'] = '</div></div>'; } } } /** Loading
commerce_ajax.schema.yml 0 → 100644 +2 −0 Original line number Diff line number Diff line views.field.commerce_ajax_edit_price: type: views.field.field
css/commerce_ajax.theme.css +0 −1 Original line number Diff line number Diff line Loading @@ -219,7 +219,6 @@ width: 42px; height: 42px; background: #b7b7b7; margin: 0.8em 0 0; border-radius: 50%; border: none; position: relative; } Loading
src/Plugin/views/field/EditPrice.php 0 → 100644 +141 −0 Original line number Diff line number Diff line <?php namespace Drupal\commerce_ajax\Plugin\views\field; use Drupal\Core\Form\FormStateInterface; use Drupal\views\Plugin\views\field\FieldPluginBase; use Drupal\views\Plugin\views\field\UncacheableFieldHandlerTrait; use Drupal\views\ResultRow; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Defines a form element for editing the order item quantity. * * @ViewsField("commerce_ajax_edit_price") */ class EditPrice extends FieldPluginBase { use UncacheableFieldHandlerTrait; /** * Constructs a new EditPrice object. * * @param array $configuration * A configuration array containing information about the plugin instance. * @param string $plugin_id * The plugin ID for the plugin instance. * @param mixed $plugin_definition * The plugin implementation definition. */ public function __construct(array $configuration, $plugin_id, $plugin_definition) { parent::__construct($configuration, $plugin_id, $plugin_definition); } /** * {@inheritdoc} */ public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { return new static( $configuration, $plugin_id, $plugin_definition ); } /** * {@inheritdoc} */ public function clickSortable() { return FALSE; } /** * {@inheritdoc} */ protected function defineOptions() { $options = parent::defineOptions(); return $options; } /** * {@inheritdoc} */ public function buildOptionsForm(&$form, FormStateInterface $form_state) { parent::buildOptionsForm($form, $form_state); } /** * {@inheritdoc} */ public function getValue(ResultRow $row, $field = NULL) { return '<!--form-item-' . $this->options['id'] . '--' . $row->index . '-->'; } /** * Form constructor for the views form. * * @param array $form * An associative array containing the structure of the form. * @param \Drupal\Core\Form\FormStateInterface $form_state * The current state of the form. */ public function viewsForm(array &$form, FormStateInterface $form_state) { // Make sure we do not accidentally cache this form. $form['#cache']['max-age'] = 0; // The view is empty, abort. if (empty($this->view->result)) { return; } $form[$this->options['id']]['#tree'] = TRUE; foreach ($this->view->result as $row_index => $row) { /** @var \Drupal\commerce_product\Entity\ProductVariationInterface $product_variation */ $product_variation = $this->getEntity($row); $form[$this->options['id']][$row_index] = [ '#type' => 'textfield', '#title' => $this->t('Price'), '#title_display' => 'invisible', '#default_value' => number_format($product_variation->getPrice()->getNumber(), 2, '.', ''), '#size' => 9, '#ajax' => [ 'callback' => 'Drupal\commerce_ajax\Plugin\views\field\EditPrice::viewsFormSubmit', 'wrapper' => '#not-exist-element', 'event' => 'change', ], '#suffix' => '<span class="currency">'.$product_variation->getPrice()->getCurrencyCode().'</span>', ]; } } /** * Submit handler for the views form. * * @param array $form * An associative array containing the structure of the form. * @param \Drupal\Core\Form\FormStateInterface $form_state * The current state of the form. */ public function viewsFormSubmit(array &$form, FormStateInterface $form_state) { $triggering_element = $form_state->getTriggeringElement(); $view = reset($form_state->getBuildInfo()['args']); $price_list = $form_state->getValue($triggering_element['#parents'][0], []); foreach ($price_list as $row_index => $price) { /** @var \Drupal\commerce_product\Entity\ProductVariationInterface $product_variation */ $view_result = $view->result[$row_index]; $product_variation = $view_result->_relationship_entities['variations']; if ($product_variation->getPrice()->getNumber() != $price) { $product_variation->setPrice(new \Drupal\commerce_price\Price($price, $product_variation->getPrice()->getCurrencyCode())); $product_variation->save(); } } return []; } /** * {@inheritdoc} */ public function query() { // Do nothing. } }