Jump to content

[SOLVED] Get selected product combination data with Javascript


Shapes

Recommended Posts

Hello,

I need to update some of my product.tpl page when the customer selects a variant.

I managed to get the variant id after selection in my theme custom.js file:
 

prestashop.on('updatedProduct',function(event) {
    let product_id = event.id_product_attribute;
});

Now I need to get the variant images ids in an array to be able to call the original images.

On the first load I display these images with (it's not very clean I know but I need unprocessed images here to be able to have multiple sizes):

<img class="" src="{$tpl_dir}../../img/p/{$image.id_image}/{$image.id_image}.jpg" alt="{$image.legend}" title="{$image.legend}" itemprop="image">

As the front ProductController.php already exists I should not have to make my own controller for this and be able to make an ajax request to it but I can't get it done. I'm struggling on the url for this request.

I tried with some threads on this form to build my request like (knowing I still need to put the product id in there):
 

prestashop.on('updatedProduct',function(event) {
    let product_id = event.id_product_attribute;

    var postdata = {
        ajax: 1,
        controller: 'Product',
        action: 'getProduct'
    $.ajax({
        type: 'POST',
        url: 'index.php',
        data: postdata,
        success: function(data){
            console.log(data);
        }
    });
});

But I get a 404 error, still struggling with url.

This thread:
https://www.prestashop.com/forums/topic/869456-how-to-display-a-product-with-ajax/
looks fine to me too but can't figure out the url part neither.

Any idea on how I could get this done please?

Edited by Shapes (see edit history)
Link to comment
Share on other sites

Well, after a lot of reading I tried to add my own module in themes/mytheme/modules.
I created a controller to extend ModuleFrontController : ajax.php in themes/mytheme/modules/ajaxproductrequest/controllers/front.

To keep it simple code looks like:

<?php 

class AjaxProductRequestAjaxModuleFrontController extends ModuleFrontController 
{ 
    public function __construct() 
    { 
        parent::__construct(); 
    } 
  
    public function initContent()
    {
        parent::initContent(); 
        return 'Hey!'; 
    } 
}

Now my ajax request in themes/custom.js looks like:

$.ajax({
    type: "POST",
    headers: { "cache-control": "no-cache" },
    url: "../../themes/mytheme/modules/ajaxproductrequest/controllers/front/ajax.php",
    data:     {
        ajax: 1,
        "token" : prestashop.token
    },
    success: function(result) {
        console.log(result);
    },
    error: function(result) {
        console.log(result);
    }
});

I also tried with url:

url: "{$link->getModuleLink('ajaxproductrequest','ajax')}"

Both lead me to the same result.
I got rid of the 404 error but now I'm stuck on an error:

Notice: Undefined index: tpl_dir

About that error, I read threads about a module compatibility error with Prestashop version, or a php version error but the module is now really simple as it is so I'm having a hard time understanding this error.

 

 

EDIT:

Looks like I got tis error appearing when switching debug mode on

Now

url: "{$link->getModuleLink('ajaxproductrequest','ajax')}"

leads to a 404 error.

And

url: "../../themes/mytheme/modules/ajaxproductrequest/controllers/front/ajax.php"

leads to a 500 error with no response details in console (which is why I turned debug mode on in the first place).

 

PS:

After some digging, Notice: Undefined index: tpl_dir came from:

<img class="" src="{$tpl_dir}../../img/p/{$image.id_image}/{$image.id_image}.jpg" alt="{$image.legend}" title="{$image.legend}" itemprop="image">

I fixed it using:

<img class="" src="{$urls.img_ps_url}p/{$image.id_image}/{$image.id_image}.jpg" alt="{$image.legend}" title="{$image.legend}" itemprop="image">

 

Edited by Shapes (see edit history)
Link to comment
Share on other sites

Well, going back to the basics in official documentation got me moving forward.

In case this can help someone spare some precious time, I'll list all steps here.

I created a module in root/modules with 2 files:
customajaxrequests > customajaxrequests.php
customajaxrequests > controllers > front > ajax.php

customajaxrequests.php content:

<?php
if (!defined('_PS_VERSION_')) {
    exit;
}

class CustomAjaxRequests extends Module
{
    public function __construct()
    {
        $this->name = 'customajaxrequests';
        $this->tab = 'front_office_features';
        $this->version = '1.0.0';
        $this->author = 'Name';
        $this->need_instance = 0;
        $this->ps_versions_compliancy = [
            'min' => '1.7',
            'max' => _PS_VERSION_
        ];
        $this->bootstrap = true;

        parent::__construct();

        $this->displayName = $this->l('Custom ajax requests');
        $this->description = $this->l('Handle custom ajax requests.');

        $this->confirmUninstall = $this->l('Are you sure you want to uninstall?');

        if (!Configuration::get('CUSTOMAJAXREQUESTS_NAME')) {
            $this->warning = $this->l('No name provided');
        }
    }

    public function install()
    {
        if (Shop::isFeatureActive()) {
            Shop::setContext(Shop::CONTEXT_ALL);
        }

        if (!parent::install()) {
            return false;
        }

        return true;
    }

    public function uninstall()
    {
        if (!parent::uninstall() || !Configuration::deleteByName('CUSTOMAJAXREQUESTS_NAME')) {
            return false;
        }

        return true;
    }
}

ajax.php content:

<?php

class CustomajaxrequestsAjaxModuleFrontController extends ModuleFrontController
{
    public function initContent()
    {
        $this->ajax = true;
        parent::initContent();
    }

    public function displayAjax()
    {
        $combinationId = (int)Tools::getValue('product_attribute_id');
        $product = new Product((new Combination($combinationId))->id_product);

        $attibuteValues = $product->getAttributeCombinationsById($combinationId,$this->context->language->id);

        die(Tools::jsonEncode(array($attibuteValues)));
    }
}

I installed the module in Prestashop Backend.

in themes/mytheme/templates/catalog/product.tpl I added:

<script>
    var ajaxRequestUrl = "{$link->getModuleLink('shapesajaxrequests', 'ajax', array())}";
</script>

in themes/mytheme/assets/js/custom.js I added:

window.addEventListener('load', function() {
    prestashop.on('updatedProduct',function(event) {
        $.ajax({
            type: 'POST',
            url: ajaxRequestUrl,
            cache: false,
            data: {
                ajax: true,
                method: 'test',
                product_attribute_id: event.id_product_attribute
            },
            success: function (result) {
                console.log(result);
            }
        });
    });
});

The good news is that it seems to work quite fine as I can pass the current product id and the selected combination id to the controller to get some data back in console like:

[[{"id_product_attribute":"5","id_product":"2","reference":"","supplier_reference":"","location":"","ean13":"","isbn":"","upc":"","mpn":"","wholesale_price":"0.000000","price":"0.000000","ecotax":"0.000000","quantity":0,"weight":"0.000000","unit_price_impact":"0.000000","default_on":null,"minimal_quantity":"1","low_stock_threshold":null,"low_stock_alert":"0","available_date":"0000-00-00","id_shop":"1","id_attribute_group":"2","is_color_group":"0","group_name":"Longueur de tige","attribute_name":"20","id_attribute":"1","position":"0"},{"id_product_attribute":"5","id_product":"2","reference":"","supplier_reference":"","location":"","ean13":"","isbn":"","upc":"","mpn":"","wholesale_price":"0.000000","price":"0.000000","ecotax":"0.000000","quantity":0,"weight":"0.000000","unit_price_impact":"0.000000","default_on":null,"minimal_quantity":"1","low_stock_threshold":null,"low_stock_alert":"0","available_date":"0000-00-00","id_shop":"1","id_attribute_group":"1","is_color_group":"1","group_name":"Couleur","attribute_name":"Blue","id_attribute":"11","position":"1"}]]

But yes, there is still a but...
The bad news is that I did not manage to get the info I need from there yet as I need to get the combination original images.
So I have some more work to get done in public function displayAjax().

Any hint would be appreciated here.

Edited by Shapes (see edit history)
Link to comment
Share on other sites

Finally got some image data by changing public function displayAjax():

public function displayAjax()
{
    $combinationId = (int)Tools::getValue('product_attribute_id');
    $product = new Product((new Combination($combinationId))->id_product);

    $images = $product->getImages($combinationId);

    die(Tools::jsonEncode(array($images)));
}

But the result stays the same when changing combination.

Shouldn't $product->getImages($combinationId) get only selected combination images instead of all the images uploaded for the product?

Link to comment
Share on other sites

Well, I don't quite understand the logic compared to previous code but I think I finally got it.

public function displayAjax()
{
    $combinationId = (int)Tools::getValue('product_attribute_id');
    $product = new Product((new Combination($combinationId))->id_product);

    $images = $product->getCombinationImages($this->context->language->id);
    $selectedCombinationImages = $images[$combinationId];

    die(Tools::jsonEncode(array($images)));
}

I do not know if it's the cleanest optimized way but it works.

I have one more thing to figure out though I think as Tools::jsonEncode() appears to be deprecated.

Edited by Shapes (see edit history)
Link to comment
Share on other sites

  • Shapes changed the title to [SOLVED] Get selected product combination data with Javascript

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...