Gravity Forms offers an excellent multi-file upload field to attach multiple files such as images to a form submission. I have used the WooCommerce Gravity Forms Add-on to add complex functionality to WooCommerce products, for example allowing customers to upload images for printing. But what happens if you want to count the number of uploaded files? Say you want to price your product based on the number of uploaded files to be processed. Normally you will need to calculate the price based on a quantity field entered by the customer since Gravity Forms does not make the number of files uploaded to a multi-file upload field available to the form. This creates a margin for error since the customer may enter the incorrect number in the quantity field.
So how do we count the number of files programmatically? With the help of Gravity Forms support team, here is a solution which makes use of the gform_pre_render hook. The hook places some Javascript on the relevant form which fires when the number of uploaded files changes, for example as files are uploaded, or if your remove uploaded files. The script updates the value of a count field (which you specify by setting the ID in the script) with the number of uploaded files. It also makes the count field read-only, to prevent manual changes to the value.
Note:
- The code should be placed in your theme’s functions.php.
- You will need to set the form ID of your form in line 6.
- You will need to set the field ID of your uploaded files count field in line 50.
- You will need to add a custom CSS class of ‘gf_readonly’ to your uploaded files count field in the form editor.
add_action( 'gform_pre_render', 'set_number_of_uploaded_images' ); // Set the uploaded images count field and make it readonly function set_number_of_uploaded_images( $form ) { // only run hook for form_id = 1 if ( $form['id'] != 1 ) { return $form; } // make any input field with the class gf_readonly to be read-only ?> <script type="text/javascript"> jQuery(document).ready(function(){ jQuery("li.gf_readonly input").attr("readonly","readonly"); }); </script> <script type="text/javascript"> gwCountFiles = function (fieldID, formID) { function getAllFiles(formID) { var selector = '#gform_uploaded_files_' + formID, $uploadedFiles = jQuery(selector), files; files = $uploadedFiles.val(); files = '' === files ? {} : jQuery.parseJSON(files); return files; } function getFiles(fieldID, formID) { var allFiles = getAllFiles(formID); var inputName = getInputName(fieldID); if (typeof allFiles[inputName] == 'undefined') allFiles[inputName] = []; return allFiles[inputName]; } function getInputName(fieldID) { return "input_" + fieldID; } var files = getFiles(fieldID, formID); return files.length; }; gform.addFilter('gform_file_upload_markup', function (html, file, up, strings, imagesUrl) { var formId = up.settings.multipart_params.form_id, fieldId = up.settings.multipart_params.field_id, targetId = 6; // set this to the field_id of your uploaded files count field html = '<strong>' + file.name + "</strong> <img class='gform_delete' " + "src='" + imagesUrl + "/delete.png' " + "onclick='gformDeleteUploadedFile(" + formId + "," + fieldId + ", this);countThemFiles(" + formId + ", " + fieldId + ", 0, " + targetId + ");' " + "alt='" + strings.delete_file + "' title='" + strings.delete_file + "' />"; countThemFiles(formId, fieldId, 1, targetId); return html; }); function countThemFiles(formId, fieldId, offset, targetId) { var count = gwCountFiles(fieldId, formId); jQuery('#input_' + formId + '_' + targetId).val(count + offset).change(); } </script> <?php return $form; }
Hello! Thak you for this scrit, its really great. The script worked well at first on my site, but I’m putting two options for radio buttons for the client:
Option 1: Send the files now
Option 2: Send later by email / cloud
If the customer chooses option 1, it shows the field to send the photos and the automatic counter of your script. If the customer chooses option 2, the file upload and automatic counter are hidden, and an option appears for the customer to manually enter the quantity.
The problem is that this way, if the customer chooses to send later, the field to fill the quantity manually is not multiplying the total value of the product.
In addition, when the customer uses option 1 and adds some files in the shipping field, the counter works fine, but if the customer switches to option 2 by mistake and returns to option 1, the automatic counter is reset, and only reactive if the customer adds more photos.
Can you help me?
Thank you very much for reading this far.
Best regards
Thanks for this Robin!
How could it work for a form that contains two separate file upload fields?
Or would that not be possible?
Thanks
Kate
Replace lines 48. 49 and 50 with this code:
var formId = up.settings.multipart_params.form_id,
fieldId = up.settings.multipart_params.field_id;
if (fieldId == 59) { // if user upload via first multi-upload field (with id 59)
var targetId = 63; // set target to count files from first multi-upload field
} else if(fieldId == 60) { // if user upload via second multi-upload field (with id 60)
var targetId = 64; // set target to count files from second multi-upload field
}
You can keep adding “else if” to add more fields.
Hello, this is really helpful. Thanks. Do you know if the number could be added to a hidden field?
Hmmm, I’d expect so. Give it a go and see if it works. I left the count field as read-only in order to give some feedback to the user, so they can see how many items they’re ordering.
Thanks, couldn’t get it to work in a hidden field – but it does work if I simply hide the text field with CSS. Another question, which is vaguely connected, I’m looking to get the filenames of the files that are uploaded so they can be added to a list field later in the form – do you think it’s doable and is there anything in your code that would help get the ball rolling? Thanks!
You’d need to modify the JavaScript to extract the filenames in the getFiles function, and set the list field values. I’d start by inserting:
at line 30, and looking at the output in the browser’s developer tools. This would show you where the filenames are stored in the allFiles array. Then you could iterate through them and write them to the list field.
Hi Robin,
I followed your instructions exactly, but I always get the following error:
ReferenceError: gform is not defined
The debugger is linking to line 47:
gform.addFilter(‘gform_file_upload_markup’, function (html, file, up, strings, imagesUrl) {
I used the correct form id, target id and class for the input field.
Do you have an idea what could have gone wrong?
Kind regards
Hi Jan-Philipp. Do you have a URL I could look at?
Robin
Hi Robin,
it is a publically hidden area of the website where Integrated it, but I made a test page for you to look it.
The good news is: on the public test page it is working. So I guess there is a javascript conflict in my non-public page template which I have to debug.
jp
Ok. Just to let you know.
There is an issue if you call the form like this:
gravity_form( 25, false, false, false, ”, false );
or like this:
echo do_shortcode(‘[gravityform id=”25″ title=”false” description=”false”]’);
I think it is the missing content filter, that screws it.
So I added the form via the content editor of my page and called it in my page template like this.
$my_id = 5369;
$post_id_5369 = get_post($my_id);
$content = $post_id_5369->post_content;
$content = apply_filters(‘the_content’, $content);
$content = str_replace(‘]]>’, ‘]]>’, $content);
echo $content;
That works now :-))
Thanks again for your quick reply 🙂
Great, glad to hear you worked it out, and thanks for sharing the solution.
Hi Rob,
Thanks for this piece of code – just what I needed! A few things of note …
The line “// make any input field with the class gf_readonly to be read-only” prints on the page, it’s not a comment 🙂 and for the next person coming along – the count field can’t be a Number field type, won’t work. Both Single Line Text field and Hidden type fields do.
Thanks again Rob. Cheers.
Oops! You’re right, the comment was outside of the PHP code. I’ve fixed it now.
Good info about the field type too, thanks!
Hello can you help me with your script? I use gravity forms for a printing website service but i can’t get it done, i have done everything step by step but it doesn’t work
I have number of photos to upload but i can’t set up to change de price based on file uploads
Thank You
I had a look at your page and I don’t see the Javascript on the page. You need to add my code to your theme’s functions.php file – have you done this?
The field to count the number of uploaded images (Numar de bucăţi din fiecare fotografie on your site) should be of type Single line text. You currently have it as Price – you will need to delete the field and recreate it as Single line text type. Then make sure you update the field ID in line 50 of the code to match your count field ID.
You have also added gf_readonly class to the upload field. This is incorrect – remove it from the upload field and add it to the count field.
Hi Roby thank you some much for reply i was wondering if you can help me with a script so that i can make it work ok
I want to use gravity forms with woocommerce but when i want to add to cart i want to use add to cart the function of woocommerce and the quantity of woocommerce replaced by “Numar de bucati din fiecare fotografie*” to gave me the corect total generated by gravity is there a posibility cause i have spend 2 weeks in searching for a solution but nothing , Thank’s
Hey Rob,
This is a great hack. Do you have an example of it in action. I am trying to do similar for a customer who wants to be able to charge for photo uploads and I can’t get the form to play ball.
Cheers
I don’t I’m afraid. What’s the problem you’re having? Maybe I can help.