Save Prestashop Custom fields on “Add to cart” – Part 1

Having to save product customization before adding to the cart can be quite annoying. Some customers might even forget to do it if the fields are not required. In the first part of this two-stage tutorial, we will see how to save customization text when the add to cart button is pressed.

  • Version used: Prestashop 1.6

Demo here

We do need Ajax

Before starting, it’s important to notice we do need to activate the ajax cart, as we will be catching the fields’ content and serialize it; then intercept the “add” method of the ajax cart and send another ajax request to the product controller, to save customized data before anything is added to the cart itself.
That said, we need to modify two javascript files, and one controller:

  • ajax-cart.js
  • tools.js
  • ProductController.php

While we can use an override for the controller, and clone the template for the ajax-cart file, we really need to amend the original tools.js, located in the main js/ folder.

That said, in this first part we will only deal with text inputs, leaving the file upload to the next tutorial.

Ajax-cart.php

After reaching the product page (of a product having a text customization field, of course), open up themes/*yourthemename*/modules/blockcart/ajax-cart.js

Locate the following method

[js]
add : function(idProduct, idCombination, addedFromProductPage, callerElement, quantity, whishlist)
[/js]

It should be around line 271 in Prestashop 1.6.0.14

Inside it, at the very beginning, right before:

[js]
if (addedFromProductPage && !checkCustomizations())
[/js]

Add the following:

[js]
if(addedFromProductPage && $(‘#customizationForm’).length > 0)
{

$(‘#quantityBackup’).val($(‘#quantity_wanted’).val());
customAction = $(‘#customizationForm’).attr(‘action’);
$(‘body select[id^="group_"]’).each(function() {
customAction = customAction.replace(new RegExp(this.id + ‘=\\d+’), this.id +’=’ + this.value);
});

}
[/js]

Explanation: first, we have to make sure we are adding to the cart from the single product view (it would make no sense in the list) and that the current item does have customization fields. What comes inside is almost a 1:1 copy of the saveCustomization() method we can find in the product.js file. We need to modify the action so that it considers attributes as well. customAction is the url we will send the ajax POST to.

Therefore, continuing from it:

[js]
if(addedFromProductPage && $(‘#customizationForm’).length > 0)
{

$(‘#quantityBackup’).val($(‘#quantity_wanted’).val());
customAction = $(‘#customizationForm’).attr(‘action’);
$(‘body select[id^="group_"]’).each(function() {
customAction = customAction.replace(new RegExp(this.id + ‘=\\d+’), this.id +’=’ + this.value);
});
// ajax to product page with custom action
var customization_entries = $(‘#customizationForm’).serialize();
$.ajax({
async:false,
type: ‘POST’,
data: customization_entries+ ‘&ajax=1’,
dataType: ‘json’,
url: customAction,
success: function(data){

}
})
}
[/js]

Explanation: after serializing the array’s entries (remember we are only using text fields for the time being), we send them over to the actionUrl (that is, the ProductController) so it can further take care of our data. Notice I also appended &ajax=1 as the controller will need to know it’s receiving an ajax request. Time to move to the override!

IMPORTANT! Make sure you set the ajax request as async:false, otherwise the add to cart will run before our customization is saved!

Note: do not try adding the product to the cart at this stage, it will not work, saying the customization field is required.

The Product Controller

Having our javascript all setup, let’s deal with the product controller. To make it quick, I will append the new method to the original file, but you can feel free to use an override instead. What it needs is a method that handles data before anything is outputted to screen. Fortunately, we don’t even need to create it, it’s built in, and it is named postProcess. The only issue is that the ProductController.php file doesn’t use, so we need to append it ourselves.

Open up controllers/front/ProductController.php, reach the end of the file, and add the following (make sure you are inside the class!)

[php]
public function postProcess()
{
if (Tools::getValue(‘ajax’) && Tools::isSubmit(‘submitCustomizedDatas’))
{
if (!$this->context->cart->id && isset($_COOKIE[$this->context->cookie->getName()]))
{
$this->context->cart->add();
$this->context->cookie->id_cart = (int)$this->context->cart->id;
}

$this->pictureUpload();
$this->textRecord();
$this->formTargetFormat();

if($this->errors)
{
$error_list = implode(‘; ‘, $this->errors);
die(Tools::jsonEncode(array(‘errors’ => $error_list)));
} else
die(Tools::jsonEncode(array(‘success’ => true)));

}
}
[/php]

Explanation: We only need to run this method for our ajax call, and only when customization data is sent over. After checking it, we simply run the methods Prestashop uses when submitting a regular customization form:

[php]

$this->pictureUpload();
$this->textRecord();
$this->formTargetFormat();

[/php]

Please notice pictureUpload is currently not being used, as we are not uploading anything. Also, we need to create a new cart in case it does not exist, before adding the text to it, so it has an id to deal with.

Then, we check for errors, sending them back to the ajax-cart.js file if there are, otherwise returning success. Since we want to make sure data has been saved, let’s go back to our JS for a second, and do something on the “success” method of the ajax call:

[js]
if(addedFromProductPage && $(‘#customizationForm’).length > 0)
{

$(‘#quantityBackup’).val($(‘#quantity_wanted’).val());
customAction = $(‘#customizationForm’).attr(‘action’);
$(‘body select[id^="group_"]’).each(function() {
customAction = customAction.replace(new RegExp(this.id + ‘=\\d+’), this.id +’=’ + this.value);
});
// ajax to product page with custom action
var customization_entries = $(‘#customizationForm’).serialize();
$.ajax({
type: ‘POST’,
data: customization_entries+ ‘&ajax=1’,
dataType: ‘json’,
url: customAction,
success: function(data){
if(typeof(data.errors != ‘undefined’))
{
alert(‘Error while saving customization data’);
return;
}

}
})
}
[/js]

We basically only added this part

[js]

if(typeof(data.errors != ‘undefined’))
{
alert(‘Error while saving customization data’);
return;
}

[/js]

To the success handler, that triggers when the ajax call is successful. Of course, you might want to expand this, and add a further level of checks to make sure data has really been saved. However, if the field is required, your product will not be added to the cart, in any case.

At this point, try writing something in the field, then click add to cart. What? Not working? Why? Prestashop can be nasty to deal with; we have to perform one last modification.

Tools.js

The last file we need to deal with might be a pain in case you upgrade. Therefore, make sure you keep a backup of the modification and/or write these steps somewhere, in case you need to apply them again. Open up js/tools.js. What we are interested in is the checkCustomizations method:

[js]
function checkCustomizations()
{
var pattern = new RegExp(‘ ?filled ?’);

if (typeof customizationFields != ‘undefined’)
for (var i = 0; i < customizationFields.length; i++)
{
/* If the field is required and empty then we abort */
if (parseInt(customizationFields[i][1]) == 1 && ($(‘#’ + customizationFields[i][0]).html() == ” || $(‘#’ + customizationFields[i][0]).text() != $(‘#’ + customizationFields[i][0]).val()) && !pattern.test($(‘#’ + customizationFields[i][0]).attr(‘class’)))
return false;
}
return true;
}
[/js]

Pay attention to the following line

[js]
function checkCustomizations()
{
if (parseInt(customizationFields[i][1]) == 1 && ($(‘#’ + customizationFields[i][0]).html() == ” || $(‘#’ + customizationFields[i][0]).text() != $(‘#’ + customizationFields[i][0]).val()) && !pattern.test($(‘#’ + customizationFields[i][0]).attr(‘class’)))
return false;

[/js]

This is what is currently preventing us from saving our customization. Actually, it gets saved, but the product is not added to the cart.
let’s get rid of a good portion of it

[js]

if (parseInt(customizationFields[i][1]) == 1 && ($(‘#’ + customizationFields[i][0]).val() == ”))
return false;

[/js]

The only thing we are doing to check it, is making sure it has a value. THat is all we need for now!
Refresh and test, it should be working now!

Next up…

Saving text customization fields when hitting the add to cart button was not too complicated. Things will get really nasty in the next tutorial, when we will deal with asynchronous file uploads! Stay tuned!

Need PrestaShop Modules? Have a look at my Prestashop Addons Store!

Looking for quality PrestaShop Web Hosting? Look no further than Arvixe Web Hosting!

Tags: , , | Posted under PrestaShop | RSS 2.0

Author Spotlight

Fabio Porta

Fabio has been involved in web development and design since 2005, when launched his first website at the age of 16. He’s now highly skilled in both client and server side development, along with design, and since August 2012 runs a successful website about PrestaShop tutorials and Prestashop Modules called Nemo’s Post Scriptum, at http://nemops.com

One Comment on Save Prestashop Custom fields on “Add to cart” – Part 1

  1. Albert says:

    It is working for me but 1 case. If user is not logged in and the cookie is not created yet, the custom field is not saved. Can someone tell me why and how to resolve it? Thanks

Leave a Reply

Your email address will not be published. Required fields are marked *