I have two attribute fields in product type set to show on the add to cart form.

Then I have an image field in the line item type created by this module to show in the add to cart form.

The behavior on the add to cart form:
- when I first select the options of the two attribute fields and then upload image to image field in the line item, the default product (the default combination of the attribute fields) is always being put into the cart
- when I first upload the image and THEN select the options of the attribute fields, the correct product is added to the cart.

So it looks like the add to cart form lose options set to attribute fields upon image upload. Just noting that options of the attribute fields visually remain selected correctly. However wrong product is put into the cart, always the default one.

Comments

xcusso’s picture

Subscribing

wla_g’s picture

I have exactly the same issue with an upload file field, but I'm not using this module. I have however used the module filefield_path, which is often combined with file or image fields. The thread opener doesn't say anything about this but maybe he ist using filefield_path as well. That could give a good indication, where the issue is coming from. Maybe he could give a clarification here.

s1work’s picture

Issue summary: View changes

Has anyone figured anything out in regards to this issue.

This is a major bug and pretty much makes the whole use of commerce useless for me at this point.

I'd love to get this working and am willing to help in any way possible.

s1work’s picture

A work around for any others that are experiencing this issue would be hiding the Upload button via CSS so that the files are upload when the product is added to cart. Unfortunately this means that you will forego the upload functionality of the field, but everything else will work as intended.

Would love to get this fixed, but until then this works.

Joe Huggans’s picture

Hi S1work.

Which upload widget are you using that uploads upon clicking the add to cart button?

I am having similar issues in that the wrong product is being added to the cart, but like you said earlier, if you change the product first it works fine.

s1work’s picture

joeuk,

I'm using just the basic upload module that comes with drupal core. I just used css to hide the upload buttons from the customers view. So instead of the customer browsing, selecting their image and then clicking the upload button, they are able to only browse and select their image and then once they click add to cart (basically submitting the form) the default nature is that the files will be uploaded.

You can see it in action at www.expediprint.com

Joe Huggans’s picture

Hi,

The default behavour for my site is that the images are not uploaded when I click add to cart.

The product is added to cart but when I navigate to the cart page, there is an error message specifying that an image is required.

Joe Huggans’s picture

I have used drag and drop upload and made it so that it uploads automatically. The only problem being that I can only upload 1 file with each order as if I allow 2, I get this odd behavior where 2 upload fields show whenever I change the product attributes from the select lists.

I think I can live with this for now, the only remaining issue is with the default product being added to the cart unless I change an attribute first in which case it works fine.

Is there a fix to this? I guess there is as this was the original issue to this thread

s1work’s picture

Do you have a link to your site? I can take a look.

Joe Huggans’s picture

hey I inboxed you

Joe Huggans’s picture

The uploading of the image causes the product to reset to a default, although this is not seen visually, it is happening because if you then add to cart it adds the wrong product.

However, if you change the product after image upload has taken place it works fine. This seems to be the same issue as what was described by the original poster of this thread.

Joe Huggans’s picture

I've tried with the method which you used. The first time I added to cart it did in fact upload the file, but then-after it has gone back to not uploading and only shows this when you navigate to the cart page.

So close yet so far away. How frustrating.

s1work’s picture

joeuk,

Are you using some kind of ajax add to cart on the product pages?

Joe Huggans’s picture

Yes!

Joe Huggans’s picture

I knew it was something stupid, thanks

s1work’s picture

Yea, I think that's the problem.

If you remove that function then when someone clicks to add to cart the file should be uploaded.

The ajax functionality would be nice, but unfortunately with the way this upload field is acting, just doesn't seem like it's an option right now.

Another nice option would be if there was a way to have it so that when someone clicks add to cart that it takes them to another page that allows them to then upload the files as part of the order process (not checkout process) and then have those files attached to the order. But I haven't found anything like that so far.

You site looks really nice. I like it.

Joe Huggans’s picture

Thanks man :) you saved a brother.

So the issue with the wrong item being added to cart is caused by the drag and drog upload widget, if I use the standard file upload it all works fine.

My only issue is that I think there needs to be some kind of indication that the file is uploading as with large file sizes it may be unclear to some users.

So maybe adding a throbber, this is something I need to figure out.

s1work’s picture

Just tried to upload and add to cart. Still resorts to the default product variation. This is what was happening to me. Something happens when you click the upload button that causes some kind of disconnect. I wish I knew how to fix it, but the only way I know to get around it is to hide the upload buttons with css so that files are uploaded when add to cart is clicked instead of the upload button.

It's an unfortunate work around and not ideal functionality, but it works and sufficient (at least for me) until a better solution is found.

As for an indicator that files are being uploaded, maybe there is some throbber or something that pops up when add to car is clicked instead of the upload button. Let me know if you figure something like that out.

Joe Huggans’s picture

What about some Jquery that runs when you click on add to cart, that makes a throbber appear or a message saying

"Uploading please wait..."

I will get back to you with some ideas once I figure it out.

I have managed to hide the upload buttons with CSS so this is ok now.

Lets just hope that this bug is ironed out at some point, the drag and drop widget is nice, I will write a bug report on the module page later anyway. :)

s1work’s picture

Yes, please let me know whatever you find out. That's a good idea about using jquery to display the message.

F.Y.I. - Your "Cart" link at the top of the page is gone.

Joe Huggans’s picture

I know, I am just guna have a link saying shopping cart, doesn't matter about showing the 'amount spent'.

I have encountered another problem which I am trying to debug now, did you ever receive

"The website encountered an unexpected error. Please try again later."

When adding a product to cart, doesn't always happen

s1work’s picture

No, but I think I have had that error from time to time on other sites. I think it's just a communication or momentary connection failure. Not sure what you can do about it.

Is it happening regularly? I haven't really had a problem with that.

Joe Huggans’s picture

It is an unusual one, doesn't seem like a Drupal error, hopefully something server side that will clear itself up.

I will get back to you in the next couple of days regarding the throbber idea. Thanks again :)

Joe Huggans’s picture

I believe my issue was with Media module. I ended up having to fall back to an earlier backup and everything is working fine now.

I have added a nice gif which basically says processing please wait and does this when someone clicks on the add to cart button

My jQuery is very simple

jQuery(document).ready(function($){
	jQuery('.form-submit').click(
        function () {
            jQuery('#loader').css({display:'block'});
         }); 
});

:)

Philben’s picture

I've hidden the file upload button as advised, but nothing is added to cart when you click on add to cart button. Any ideas please?

Joe Huggans’s picture

Are you sure it hasn't added to cart? Or just that the cart which is a view, has not been configured to show if a file has been uploaded?

Philben’s picture

Thanks Joeuk. Yes I'm sure; the customised product was not added to cart. Page reloads alright, but product is not added to cart. It only adds to cart when file upload field is removed. It's very frustrating.

Philben’s picture

I found the problem, the form was actually not submitting due to jQuery I was using to validate required fields. For some reason, event.preventDefault() and submit() didn't work.

$('#submit').on('click', function(event){
       event.preventDefault();

     if($('.error').length === 0){
       $(this).closest('form').submit();
     }
}) 

Use this instead:

$('#submit').on('click', function(){
       $(this).closest('form').submit( function(){
              if($('.error').length === 0){
                return true;
             }
       });
    
}) 
argiepiano’s picture

Confirming that this issue still exists - having another ajax callback (for example to upload a file) conflicts with the ajax used by the Add to Cart form to rebuild the form with the product that matches the product attributes. Hiding the file upload button with css seems to be the only workaround here.

i.koychev’s picture

I have the same issue with the basic file upload single value field added to the line item type. After file upload submitted the attribute fields lose their values but stay selected correctly. After add to cart submitted the first variation of the product was added to the shopping cart. I think that the problem occurs in file_upload_ajax function (in file.module) which retrieves the form state values from cache.
list($form, $form_state, $form_id, $form_build_id, $commands) = ajax_get_form();
The code below seems to solve my problem.

function file_ajax_upload_callback($form, &$form_state) {

  // Only the first five lines are changed form the original file_ajax_upload() function.
  // Also the line list($form, $form_state, $form_id, $form_build_id, $commands) = ajax_get_form(); was removed.
  $form_parents = isset($form_state['triggering_element']['#parents']) ? array($form_state['triggering_element']['#parents']) : array($form_state['triggering_element']['#array_parents']);
  $form_parents = reset($form_parents);
  array_pop($form_parents); // remove 'button';
  $form_build_id = $form['#build_id'];

  if (!isset($form_build_id) || empty($form_build_id)) {
    // Invalid request.
    drupal_set_message(t('An unrecoverable error occurred. The uploaded file likely exceeded the maximum file size (@size) that this server supports.', array('@size' => format_size(file_upload_max_size()))), 'error');
    $commands = array();
    $commands[] = ajax_command_replace(NULL, theme('status_messages'));
    return array('#type' => 'ajax', '#commands' => $commands);
  }

  if (!$form) {
  // Continue with the same code as in original file_ajax_upload() function.

}

function _mymodule_file_managed_file_process($element, &$form_state, $form) {

  // Process $element as normal.
  $element = file_managed_file_process($element, $form_state, $form);

  // Replace ajax path with ajax callback function.
  unset($element['upload_button']['#ajax']['path']);
  $element['upload_button']['#ajax']['callback'] = 'file_ajax_upload_callback';

  return $element;
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function mymodule_form_commerce_cart_add_to_cart_form_alter(&$form, &$form_state, $form_id) {

  if (isset($form['line_item_fields'])) {

    // Check for file upload in line item fields. Not sure that this is the right way to brows all line item fields
    // to find the upload fields and replace their file_managed_file_process width custom function.
    // I develop the multilingual print shop with using entity translations for line item fields.
    $line_item_fields = &$form['line_item_fields'];
    foreach (element_children($line_item_fields) as $field_name) {
      $field_lang = $line_item_fields[$field_name]['#language'];
      $deltas = element_children($line_item_fields[$field_name][$field_lang]);
      if (count($deltas) > 0) {
        $delta = reset($deltas);
        $element = &$line_item_fields[$field_name][$field_lang][$delta];
      }
      else {
        $element = &$line_item_fields[$field_name][$field_lang];
      }
      if (isset($element['#type']) && $element['#type'] == 'managed_file') {
        foreach ($element['#process'] as $key => $process_function_name) {

          //  Replace file_managed_file_process with custom function.
          if ($process_function_name == 'file_managed_file_process') {
            $element['#process'][$key] = '_mymodule_file_managed_file_process';
            break;
          }
        }				
      }
    }
  }  
}
hristos’s picture

in which file the changes should be made

Joe Huggans’s picture

My code is below, I can not get this working, the ajax uploading takes around 60 seconds and it still adds the wrong product after. I am willing to pay if someone can look into this for me please

Joe Huggans’s picture

.

Joe Huggans’s picture

/**
 * Implements hook_form_alter().
 */
function form_alter_form_alter(&$form, &$form_state, $form_id) {
    
    if ($form_id === 'commerce_cart_add_to_cart_form_CHQU73IYWMGr6uPDEWPhR9tSmUbATM6TU2DS-v1hkHU') {
    	$form['#after_build'][] = 'form_alter_after_build'; 
    }

}

function form_alter_after_build($form, &$form_state) {
	array_push($form['line_item_fields']['field_upload_images'][LANGUAGE_NONE][0]['#process'], 'fix_ajax_upload');
	return $form;
}


function fix_ajax_upload($element, &$form_state, $form) {
  
	$element = file_managed_file_process($element, $form_state, $form);
	unset($element['upload_button']['#ajax']['path']);
	$element['upload_button']['#ajax']['callback'] = 'form_alter_ajax_upload_callback';
	return $element;

}


function form_alter_ajax_upload_callback($form, &$form_state) {


  $form_parents = isset($form_state['triggering_element']['#parents'][0]) ? array($form_state['triggering_element']['#parents'][0]) : array($form_state['triggering_element'] ['#array_parents'][0]);
  $form_build_id = $form['#build_id'];


  if (!isset($form_build_id) || empty($form_build_id)) {
    // Invalid request.
    drupal_set_message(t('An unrecoverable error occurred. The uploaded file likely exceeded the maximum file size (@size) that this server supports.', array('@size' => format_size(file_upload_max_size()))), 'error');
    $commands = array();
    $commands[] = ajax_command_replace(NULL, theme('status_messages'));
    return array('#type' => 'ajax', '#commands' => $commands);
  }


  if (!$form) {
    // Invalid form_build_id.
    drupal_set_message(t('An unrecoverable error occurred. Use of this form has expired. Try reloading the page and submitting again.'), 'error');
    $commands = array();
    $commands[] = ajax_command_replace(NULL, theme('status_messages'));
    return array('#type' => 'ajax', '#commands' => $commands);
  }

  // Get the current element and count the number of files.
  $current_element = $form;
  foreach ($form_parents as $parent) {
    $current_element = $current_element[$parent];
  }
  $current_file_count = isset($current_element['#file_upload_delta']) ? $current_element['#file_upload_delta'] : 0;

  // Process user input. $form and $form_state are modified in the process.
  drupal_process_form($form['#form_id'], $form, $form_state);

  // Retrieve the element to be rendered.
  foreach ($form_parents as $parent) {
    $form = $form[$parent];
  }

  // Add the special Ajax class if a new file was added.
  if (isset($form['#file_upload_delta']) && $current_file_count < $form['#file_upload_delta']) {
    $form[$current_file_count]['#attributes']['class'][] = 'ajax-new-content';
  }
  // Otherwise just add the new content class on a placeholder.
  else {
    $form['#suffix'] .= '<span class="ajax-new-content"></span>';
  }

  $form['#prefix'] .= theme('status_messages');
  $output = drupal_render($form);
  $js = drupal_add_js();
  $settings = drupal_array_merge_deep_array($js['settings']['data']);

  $commands[] = ajax_command_replace(NULL, $output, $settings);
  return array('#type' => 'ajax', '#commands' => $commands);

}
timcamps’s picture

Since none of the above would work in my case, I hacked together some jQuery which solves the problem.

Basically, what I'm doing is calling the Attribute selection again after the Upload button is clicked. This way the image gets uploaded and the attribute selection gets saved.

This results in the following js:

// Track clicks on the Upload button
var fire; // This is used to avoid a continuous loop on the ajaxComplete event
Drupal.behaviors.uploadButtons = {
    attach: function (context) {
    jQuery('button.form-submit', context).bind('mousedown', Drupal.upload.Fired ); // If the Upload button is clicked ...
    }
};
Drupal.upload = Drupal.upload || {
    Fired : function(){
        fire = true; // ... set the event to true
    }
};

Then, on an ajaxComplete event, this code gets fired:

jQuery(document).ajaxComplete(function() {
	
	// Fire the Product Attribute selection again
	if (fire) {
	var parent = jQuery('.form-type-commerce-fancy-attributes-ajax .description .description-selected').parent().parent();
        jQuery('input[type=radio]', parent).click();
        jQuery('input[type=radio]', parent).change();
        fire = false; // Set fire to False to avoid a continuous loop here
	} 
  
});

If anyone cares to optimise my hacked code, be my guest.

In the meantime, I hope this helps you out.