Discussions

Commerce add to cart form fails when loaded via Ajax

I'm setting up a store page as follows, using Views, Commerce, and Drupal AJAX via a custom module:

http://i.stack.imgur.com/pwREd.png

There is a View that lists product display Nodes (B). Clicking on a Node in the View loads that Node's 'full' view on the page via AJAX (C), which includes the Product reference field / add to cart form (D). There are also AJAX links (A) that will swap the View for another display of the same view (with different criteria for loading the Nodes). The add to cart button works on Nodes included in the View display that loads initially on the page, but not if the View display is switched. When clicked, the form submits, but the product is never added to the cart. No errors or log messages. The exception is that any product Nodes that were loaded in the initial View display will work in subsequent ones.

So if 'new_releases' is the Views display loaded during the initial page load, and it includes 'title 1', then when 'title 1' is loaded, then the 'buy' button works. If 'full_catalog' is then loaded, then 'title 1' is loaded, then the 'buy' button works. But if 'full_catalog' includes 'title X', not included in 'new_releases', then they 'buy' button won't work when 'title X' is loaded.

This makes me think something is going on (perhaps with form_token or form_build_id) that gets initialized properly during the first page load that doesn't happen via subsequent AJAX loads, but I'm not sure what that would be. The form HTML seems to be correct in both cases, both include the product ID and hidden quantity fields. No error messages shown.

Here's my code that loads the node:

<?php
   
function my_module_node_loader($nid = 0) {
    
$node = node_load($nid, NULL, false);

     if(
$node) {
      
$nodeview = node_view($node,'full');
       return
render($nodeview); //will be returned in my_module_ajax_callback via drupal_json_output
    
}
   }
?>

The function that retrieves the view:

<?php
   
function my_module_store_contents($display) {
   
    
$view = views_get_view('view_name');
    
$view->set_display($display);
    
$view->execute();
    
$response = $view->result;
    
    
     foreach(
$response as $id=>$row) {
      
//do some custom formatting, put the results in $html
    
}
    
      return
$html; //returned via my_module_block_view on intial page load, my_module_ajax_callback subsequently
  
}
?>

I'm already sure the AJAX callbacks are working ok, as the content gets loaded as I'd expect. It's just the issue with the form. Is there an extra step to make sure that a form is initialized properly if loaded via AJAX?

Posted: Oct 30, 2013

Comments

adam.harvie on November 6, 2013

Thanks for the reply. It made me revisit my form_alter function, which I'd forgotten about:

<?php
function my_module_form_commerce_cart_add_to_cart_form_alter(&$form, &$form_state) {
   
     if(
substr($form['#action'],0,15) == '/my-module/ajax') {
      
$form['#action'] = '/shop';
      
$form_state['rebuild'] = TRUE;
     }

   }
?>

The 'rebuild' doesn't seem to help, but it did make me realize that the problem is my altering the #action - if I remove that, then the product is added to the cart. The remaining issue is that it loads the '/my-module/ajax' url on submit instead of reloading the shop page. This is why I was altering the action in the first place: the add to cart form seems to get its #action from the menu callback that generated it.

So it looks like I should look at making the form submit via ajax instead of trying to reload the page, or look at a method of altering the form #action that doesn't break it.