Edit: more details below
I'm setting up a store page as follows, using Views, Commerce, and Drupal AJAX via a custom module:
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:
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:
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?
Edit:
Thanks to a tip on drupal commerce's site, I discovered the cause of this was my altering the form's #action, which I had forgotten about. The add-to-cart form seems to take its #action from the path that loads it, so rather my /shop url, it was trying to load the /my-module/ajax callback. Since the add-to-cart form isn't itself ajax-enabled, it was redirecting the page with that url rather than doing it via ajax - I'd get the JSON response - so I was attempting to set the #action back to /shop:
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;
}
}
I attempted to use the 'rebuild' directive, with no effect. But if I remove the code altering the #action, then the product is added to the cart, albeit first sending me to /my-module/ajax.
So I need to either alter the add-to-cart form to submit properly via ajax, or figure out how I can alter the #action without breaking the form.