1

On a product node there is form with a button "add to cart" that is implemented with form API (ajax):

$form['add_to_cart'] = array(
  '#type' => 'button',
  '#value' => $this->t('Add to cart'),
  '#ajax' => array(
    'callback' => 'Drupal\custom_cart\Form\AddToCartForm::addProductToCart',
    'event' => 'click',
    'effect' => 'fade',
    'wrapper' => '#custom-cart', 
    'progress' => array(
      'type' => 'throbber',
    ),
  )
);

...

public function addProductToCart(array &$form, FormStateInterface $form_state) {
if ($parent_node_id = $form_state->getStorage()['parent_node_id']) {
  if ($product_node = Node::load($parent_node_id)) {
    $pid = $product_node->get('field_product_bid')->value;
    $price = $product_node->get('field_product_price')->value;
    $renderer = \Drupal::service('renderer');
    $response = new AjaxResponse();
    Cart::addLineItem($pid, $form_state->getValue('amount'), $price);
    $cart = Cart::getThemedCart();
    $elem = ['#markup' =>  $cart];
    $response->addCommand(new ReplaceCommand('.cart-nav', $renderer->render($elem)));
    return $response;
  }
 }
}

This works as expected.

For a product overview page we render out product nodes with a view (node teasers) and the view includes some exposed filters. If the view is ajax enabled the ajax callback from the "add to cart" button (breaks) and returns a 404 error:

Request URL:http://foobar.lo/views/ajax?_wrapper_format=drupal_ajax Request Method:POST Status Code:404 Not Found

Does somebody know how to fix this (core patches anywhere?) or a workaround you know?

Thanks for any advice

  • Better you can add code of method addProductToCart. Maybe the issue comes with this method. – Jonh Nov 13 '17 at 8:29
  • The callback returns a 404 (for the fapi ajax) so the method is not called. The issue is probably related to js attach logic – lenni Nov 14 '17 at 12:34
3
+200

The issue is in this line of RenderElement::preRenderAjaxForm:

$settings['url'] = Url::fromRoute('<current>');

When the form with the button "add to cart" is rendered inside of an ajax request of a view, then the url is set to the wrong endpoint /views/ajax.

A workaround would be to add a static url in the ajax setting of the form element, so that it won't be set dynamically:

use Drupal\Core\Form\FormBuilderInterface;

  '#ajax' => [
    'callback' => '::add',
    'wrapper' => $wrapper,
    'url' => Url::fromRoute('<front>'),   // set this to the route of the view page
    'options' => ['query' => \Drupal::request()->query->all() + [FormBuilderInterface::AJAX_FORM_REQUEST => TRUE]],
  ]

If you use the form in multiple pages you would need to adjust the code to only set the url when the form is rendered in this view.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.