Reputation: 11
We currently have a whole category of products where they all have the same combinaisons (ex : each product is available as packs of : 1, 3, 5, 10, 25, 50, 100 with decreasing prices)
EDIT : The products from this category are being displayed on the homepage using an owl-carousel which is inside a div =>
<div id="carousel-2642346269" class="owl-carousel owl-theme product-default owl-loaded">
When a customer use the dropdown selector (located under each products) and select a different combinaison, the prices (unit price and total price of the product) are being updated by the call to psajax.php :
Here is the custom "filter" we would like to implement on the homepage of a Prestashop 1.7.7. installation which you can see on the first screenshot located just above the products pictures. Intended behavior would be like this : When a customer select the 2nd radio button (3 GRAMMES) a request would be made to psajax.php and instead of updating prices for JUST ONE product like it does right now, it would update it for every product of this category.*
<form>
<label class="radio-inline">
<input type="radio" name="optradio" onclick="showPrices(this.id);" id="0" checked>
Set selector on the attribute 0 for every product from category 21.
</label>
<label class="radio-inline">
<input type="radio" name="optradio" onclick="showPrices(this.id);" id="1">
Set selector on the 1st attribute for every product from category 21.
</label>
<label class="radio-inline">
<input type="radio" name="optradio" onclick="showPrices(this.id);" id="2">
Set selector on the 2nd attribute for every product from category 21.
</label>
<label class="radio-inline">
<input type="radio" name="optradio" onclick="showPrices(this.id);" id="3">
Set selector on the 3rd attribute for every product from category 21.
</label>
<label class="radio-inline">
<input type="radio" name="optradio" onclick="showPrices(this.id);" id="4">
Set selector on the 4th attribute for every product from category 21.
</label>
<label class="radio-inline">
<input type="radio" name="optradio" onclick="showPrices(this.id);" id="5">
Set selector on the 5th attribute for every product from category 21.
</label>
<label class="radio-inline">
<input type="radio" name="optradio" onclick="showPrices(this.id);" id="6">
Set selector on the 6th attribute for every product from category 21.
</label>
</form>
Currently this is the ajax call used to retrieve the new product attributes by sending a request to psajax.php whenever a customer select a different combinaison from the dropdown selector of a product :
$.ajax({
type: 'POST',
headers: {"cache-control": "no-cache"},
url: prestashop.urls.base_url + 'modules/mymodule/psajax.php?rand=' + new Date().getTime(),
async: true,
cache: false,
data: {
"action": "get-attribute-data",
"id_product": id_product,
"id_product_attribute": id_attr,
"token": xyz_token
},
success: function (result)
{
if(result != '')
{
var obj = $.parseJSON(result);
// console.log($(this));
// console.log($('.product-miniature[data-id-product=' + id_product+']'));
$product_article_e.find('.product-thumbnail img').attr('src', obj.product_cover.bySize.home_default.url).attr('alt', obj.product_cover.legend);
$product_article_e.find('.product-thumbnail').attr('href', obj.product_url);
$product_article_e.find('.product-price-and-shipping').empty().append(obj.price_attribute);
// if (typeof enable_product_label != 'undefined' && enable_product_label)
// {
// updatePostionLabel($product_article_e);
// }
}
else
{
alert(add_cart_error);
}
$('.xyz-bt-cart.active').find('.xyz-bt-cart-content').fadeIn('fast');
$('.xyz-bt-cart.active').find('.leo-loading').hide();
$('.xyz-bt-cart.active').removeClass('active reset');
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert("TECHNICAL ERROR: \n\nDetails:\nError thrown: " + XMLHttpRequest + "\n" + 'Text status: ' + textStatus);
}
});
And this is the part of psajax.php that send back the new price attriutes for the selected combinaison :
if (Tools::getValue('action') == 'get-attribute-data') {
$result = array();
$context = Context::getContext();
$id_product = Tools::getValue('id_product');
$id_product_attribute = Tools::getValue('id_product_attribute');
$attribute_data = new LeofeatureProduct();
$result = $attribute_data->getTemplateVarProduct2($id_product, $id_product_attribute);
die(Tools::jsonEncode(array(
'product_cover' => $result['cover'],
'price_attribute' => $module->renderPriceAttribute($result),
'product_url' => $context->link->getProductLink($id_product, null, null, null, $context->language->id, null, $id_product_attribute, false, false, true),
)));
}
What would be the proper way to implement this filter and is it even possible ?
EDIT 3 :
I'd like to update the dropdown selector of each products inside the carousel when their prices are updated using the new function but i cannot figure out the way to properly fetch the attribute id i need.
The attribute ids dropdown looks like this :
<div class="dropdown leo-pro-attr-section">
<button class="btn btn-secondary dropdown-toggle leo-bt-select-attr dropdownListAttrButton_34" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> Poids - 1g </button>
<div class="dropdown-menu leo-dropdown-attr">
<a class="dropdown-item leo-select-attr selected" href="#" data-id-product="34" data-id-attr="284" data-qty-attr="10" data-min-qty-attr="1">Poids - 1g</a>
<a class="dropdown-item leo-select-attr" href="#" data-id-product="34" data-id-attr="286" data-qty-attr="10" data-min-qty-attr="1">Poids - 3g</a>
<a class="dropdown-item leo-select-attr" href="#" data-id-product="34" data-id-attr="288" data-qty-attr="10" data-min-qty-attr="1">Poids - 5g</a>
<a class="dropdown-item leo-select-attr" href="#" data-id-product="34" data-id-attr="289" data-qty-attr="10" data-min-qty-attr="1">Poids - 10g</a>
<a class="dropdown-item leo-select-attr" href="#" data-id-product="34" data-id-attr="290" data-qty-attr="10" data-min-qty-attr="1">Poids - 25g</a>
<a class="dropdown-item leo-select-attr" href="#" data-id-product="34" data-id-attr="291" data-qty-attr="10" data-min-qty-attr="1">Poids - 50g</a>
<a class="dropdown-item leo-select-attr" href="#" data-id-product="34" data-id-attr="292" data-qty-attr="5" data-min-qty-attr="1">Poids - 100g</a>
</div>
And the JS function called to update prices :
var res2 = $($.parseJSON(result))
var res3 = res2.result;
for (const productId of productIds) {
var $product_article_e = $('.leo-select-attr').parents('.product-miniature[data-id-product=' + productId+']');
res2.each(function( productId, product ) {
let inside = this.result;
$.each(inside, function(k,v){
let productArticle = $('.leo-select-attr').parents('.product-miniature[data-id-product=' + k+']');
productArticle.find('.product-thumbnail img').attr('src', v.product_cover.bySize.home_default.url).attr('alt', v.product_cover.legend);
productArticle.find('.product-thumbnail').attr('href', v.product_url);
productArticle.find('.product-price-and-shipping').empty().append(v.price_attribute);
});
});
}
And psajax.php :
if ($variante == '0') {
$res_final = $attribute_data->getTemplateVarProduct2($productId, $result[$productId]['variante_1g']);
$result[$productId]['product_cover'] = $res_final['cover'];
$result[$productId]['price_attribute'] = $module->renderPriceAttribute($res_final);
$result[$productId]['product_url'] = $context->link->getProductLink($productId, null, null, null, $context->language->id, null, $result[$productId]['variante_1g'], false, false, true);
$i++;
} elseif ($variante == '1') {
//$res_final = $attribute_data->getTemplateVarProduct2($productId, $productAttributeId);
$res_final = $attribute_data->getTemplateVarProduct2($productId, $result[$productId]['variante_3g']);
$result[$productId]['product_cover'] = $res_final['cover'];
$result[$productId]['price_attribute'] = $module->renderPriceAttribute($res_final);
$result[$productId]['product_url'] = $context->link->getProductLink($productId, null, null, null, $context->language->id, null, $result[$productId]['variante_3g'], false, false, true);
$i++;
} elseif ($variante == '2') {...
Upvotes: 0
Views: 332
Reputation: 447
It is not entirely clear where you want to use this, and what do you mean by:
What would be the proper way to implement this filter ?
Are there currently a couple of products from this category listed on the home page? And do you want to apply the filter to these products?
Regardless of all this, I think that the best way is to create a custom module, and implement the "displayHome" hook.
And implement all of your code in that module.
Update: How the PrestaShop filter works: you submit a few parameters and return a list of products that meet the criteria.
If I interpreted your code correctly, it won’t do that.
And you're using some jQuery selectors in the code that tell us nothing. Please upload even images to your question to get clear of what you want to achieve and where you are currently.
UPDATE 2:
Just do the same operation with bulk update. Create a JavaScript function, which collects all the products ID-s and send to psajax with optradio value.
...
<label class="radio-inline">
<input type="radio" name="optradio" onclick="bulkUpdate(this.id);" id="0" checked>
Set selector on the attribute 0 for every product from category 21.
</label>
...
the bulkUpdate JS function:
function bulkUpdateProducts(optID){
var productIds = [];
var productAttributeIds = [];
$('.owl-carousel ...extend with the right selector').each(function () {
productIds.push(this.id);
productAttributeIds[this.id] = $('get the product attribute ID you need based on the optID. If the optId == 1, the you need the ID of 1 gramme HTML element');
});
//call the Ajax, with data:
data: {
"action": "get-attribute-data-bulk",
"id_products": productIds,
"id_product_attributes": productAttributeIds,
"token": xyz_token
},
}
The new psajax.php method:
if (Tools::getValue('action') == 'get-attribute-data-bulk') {
$result = array();
$res = '';
$context = Context::getContext();
$productIds = Tools::getValue('id_products');
$productAttributeIds = Tools::getValue('id_product_attributes');
foreach($productIds as $productId){
$attribute_data = new LeofeatureProduct();
$res = $attribute_data->getTemplateVarProduct2($productId, $productAttributeIds[$productId]);
$result[$productId]['product_cover'] = $res['cover'];
$result[$productId]['price_attribute'] = $module->renderPriceAttribute($res),
$result[$productId]['productUrk'] = $context->link->getProductLink($productId, null, null, null, $context->language->id, null, $ $productAttributeIds[$productId], false, false, true),
}
die(Tools::jsonEncode(
'result' => $result
));
}
and process the ajax response
if(result != '')
{
var res = $.parseJSON(result);
res.each(function( productId, product ) {
// search the product HTML element which do you want to update by productId, and update
// something like this, but you need to find the right jquery selectors
let productArticle = $('.product-miniature[data-id-product=' + productId+']');
productArticle.find('.product-thumbnail img').attr('src', obj.product_cover.bySize.home_default.url).attr('alt', obj.product_cover.legend);
productArticle.find('.product-thumbnail').attr('href', obj.product_url);
productArticle.find('.product-price-and-shipping').empty().append(obj.price_attribute);
});
}
Please note that this is just a sketch. You need to extend with the right Jquery selectors, etc.
Upvotes: 0