Vote up!
Vote down!

Add to cart not working on Views pages with exposed filters and AJAX enabled

Hello Commerce Guys,

On AJAX enabled Views with exposed filters or pagers the "Add to cart" button not working. After an AJAX call, the add-to-cart form action changes to views/ajax. This could be easily avoided with jQuery or form_alter(), but the cart do not updated either.

The problem was mentioned earlier, you answer was to ask the reporter to reproduce the steps...so, here they are...

On a fresh install of Commerce Kikstart and Drupal7.26 do the following steps:

1. Content / Content types / Drinks / Manage display
Change "Product variations" display from "Field Extractor" to "Add to Cart form"

2. Site settings / Views / Collections product
Add a new filter criteria: Indexed Node: Cagtegory
Make this filter exposed.

3. Turn AJAX on at Advanced / Other / Use AJAX and save the view.

4. At the frontend go to /?q=collection/drink (To Drink With at the main menu), and use the exposed category filter (filter the content for "Coffee Mugs" for example).

5. Use one of the "Add to cart" buttons...

I hope, this will be solved... Thanks!


Asked by: efes
on January 30, 2014

1 Answer

Vote up!
Vote down!

I sorta found a workaround for this by hooking into hook_views_ajax_data_alter to do a str_replace on the $command['data'] to change the add-to-cart form actions in the actual markup.

In my case, (using Better Exposed Filters to print out filter options as links instead of radio buttons) selecting each exposed filter option re-renders several product teasers each with add-to-cart forms, so there are several places in the $command['data'] markup that this str_replace takes place.

This does successfully change the add-to-cart forms' #action from 'action="views/ajax"' to 'action="[current page url]"'.

However when you try to actually add an item to your cart, this seemingly correct form action still only refreshes the page and does not add the item to your cart.

Through trial and error, I discovered that if the new form action contains the exposed filter identifier and filter id number (taxonomy term name and term id, respectively, in my case) in the querystring like this: http://www.example.com/view-with-exposed-filter?filter-identifier=123; then and only then will it actually add the item to the cart.

However (as form actions do) this posts the form to that page with the querystring and subsequent exposed filter selections and view re-renderings (via AJAX) will not change the url to use the currently selected filter id number in the querysting, so when the add-to-cart form posts again, the item will not be added to the cart unless the item you're adding belongs to the filter id (taxonomy term) in the url.

FWIW, here's my code. Maybe someone can help me better understand why the AJAX rendered add-to-cart forms must supply the correct exposed form filter identifier in the form action to actually add the item to the cart instead of just refreshing the page... while this isn't the case on the initial (non-AJAX) load of a view with exposed form filters where add-to-cart forms work without the filter id specified in the form action.

* Implements hook_views_ajax_data_alter()
function hook_views_ajax_data_alter(&$commands, $view) {
  // Get the variable options from the view object.
  $options = $view->query->pager->display->display_options;

  // Make sure this view is using ajax and BEF exposed filters
  $use_exposed = (isset($options['use_ajax']) && isset($options['exposed_form']) && $options['exposed_form']['type'] == 'better_exposed_filters') ? TRUE : FALSE;

  // In the command's data replace 'action="/views/ajax"' to 'action="[current page url]"'
  // See: views_ajax_fade contrib module
  if ($use_exposed) {
    foreach ($commands as &$command) {
      if (isset($command['method']) && $command['method'] == 'replaceWith') {
        $path_alias = url(drupal_lookup_path('alias', current_path()));
        //$path_alias = 'http://www.example.com/view-with-exposed-filter?filter-identifier=123';
        $command['data'] = str_replace('action="/views/ajax"', 'action="'.$path_alias.'"', $command['data']);


Wesley Musgrove
Answer by: Wesley Musgrove
Posted: Jun 23, 2015