6

I am trying to display a custom product attribute under the order summary list of items on checkout. I think it is fed by the TotalsItemExtensionInterface. I have the following trying to add the custom attribute to the collection exposed on the front end.

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
<extension_attributes for="Magento\Quote\Api\Data\TotalsItemExtensionInterface">
    <attribute code="product" type="string">
        <join reference_table="catalog_product" reference_field="product_id" join_on_field="entity_id">
            <field>custom_attribute</field>
        </join>
    </attribute>
</extension_attributes>
</config>

Any ideas on how this is done to attach a product attribute to a quote item in Magento 2?

EDIT: Attached is the screenshot of where I would like to get the attribute to show: enter image description here

Also I am taking a different route, but have the same problem. I brought the attribute to the quote item through a migration so is now part of the quote_item table. But not part of the collection coming through. Any idea on how I get that attribute as part of the quoteItem object?

4
  • You can take a screenshot and show where you want show the custom product attribute? – Khoa TruongDinh Aug 28 '16 at 3:30
  • @KhoaTruongDinh Uploaded image and also an update. Still having this issue. – sudopratt Aug 29 '16 at 19:00
  • How about your current issue? – Khoa TruongDinh Sep 1 '16 at 16:29
  • Try this fix: github.com/magento/magento2/issues/3640 But in your case, having a join with catalog_product entity looks like too much. – Daniel Ifrim Sep 28 '16 at 13:47
11

1) The flow of cart summary in checkout page

We can get the totalsData from:

vendor/magento/module-checkout/view/frontend/web/js/model/quote.js

var totalsData = window.checkoutConfig.totalsData;

return {
    totals: totals,
    ......
}

If we try to format the Json from window.checkoutConfig, we can see the totalsData. And, we can get the items from it.

enter image description here

Now, at look the checkout xml layout:

vendor/magento/module-checkout/view/frontend/layout/checkout_index_index.xml

<item name="cart_items" xsi:type="array">
    <item name="component" xsi:type="string">Magento_Checkout/js/view/summary/cart-items</item>
    <item name="children" xsi:type="array">
        <item name="details" xsi:type="array">
            <item name="component" xsi:type="string">Magento_Checkout/js/view/summary/item/details</item>
            <item name="children" xsi:type="array">
                <item name="thumbnail" xsi:type="array">
                    <item name="component" xsi:type="string">Magento_Checkout/js/view/summary/item/details/thumbnail</item>
                    <item name="displayArea" xsi:type="string">before_details</item>
                </item>
                <item name="subtotal" xsi:type="array">
                    <item name="component" xsi:type="string">Magento_Checkout/js/view/summary/item/details/subtotal</item>
                    <item name="displayArea" xsi:type="string">after_details</item>
                </item>
            </item>
        </item>

    </item>
</item>

In the front page:

enter image description here

2) Add custom attribute

Where is the totalsData from the PHP side?

vendor/magento/module-checkout/Model/DefaultConfigProvider.php

public function getConfig()
{ 
    ......
    $output['postCodes'] = $this->postCodesConfig->getPostCodes();
    $output['imageData'] = $this->imageProvider->getImages($quoteId);
    $output['totalsData'] = $this->getTotalsData();
    ......
}

So, we need to override this method, I think we should use Plugin to override this method.

Vendor\Module\etc\di.xml

<type name="Magento\Checkout\Model\DefaultConfigProvider">
        <plugin name="add_custom_product_attribute" type="Vendor\Module\Model\Checkout\ConfigProviderPlugin" />
</type>

Vendor\Module\Model\Checkout\ConfigProviderPlugin.php

public function afterGetConfig(\Magento\Checkout\Model\DefaultConfigProvider $subject, array $result)
{
    $items = $result['totalsData']['items'];
    foreach($items as $item) {
        //Your code here
    }

    return $result;
}

And then, we need to create your own js and html template files or override the exist files.

[EDIT]

We should try with:

The proper way is to use TotalsItemExtensionInterface and add all these via it

Create extension attributes:

app/code/Vendor/Module/etc/extension_attributes.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
    <extension_attributes for="Magento\Quote\Api\Data\TotalsItemExtensionInterface">
        <attribute code="reward_points" type="int" />
    </extension_attributes>
</config>

app/code/Vendor/Module/etc/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Quote\Model\Cart\Totals\ItemConverter">
        <plugin name="show-points-item" type="Vendor\Module\Plugin\Cart\Totals\ItemConverterPlugin" sortOrder="10"/>
    </type>
</config>

app/code/Vendor/Module/Plugin/Cart/Totals/ItemConverterPlugin.php

<?php

namespace Vendor\Module\Plugin\Cart\Totals;

use Magento\Quote\Model\Cart\Totals\ItemConverter;
use Magento\Quote\Api\Data\TotalsItemExtensionFactory;

class ItemConverterPlugin
{
    /**
     * @var TotalsItemExtensionFactory
     */
    protected $totalsItemExtensionFactory;

    /**
     * ItemConverterPlugin constructor.
     *
     * @param TotalsItemExtensionFactory $totalsItemExtensionFactory
     */
    public function __construct(
        TotalsItemExtensionFactory $totalsItemExtensionFactory
    ) {
        $this->totalsItemExtensionFactory = $totalsItemExtensionFactory;
    }

    /**
     * @param ItemConverter $subject
     *
     * @param $result
     * @return mixed
     */
    public function afterModelToDataObject(
        ItemConverter $subject,
        $result
    ) {
        $extensionAttributes = $result->getExtensionAttributes();
        if ($extensionAttributes === null) {
            $extensionAttributes = $this->totalsItemExtensionFactory->create();
        }
        $pointsDelta = 24;
        $extensionAttributes->setRewardPoints($pointsDelta);
        $result->setExtensionAttributes($extensionAttributes);
        return $result;
    }
}

On the checkout page, we can check on Browser console: window.checkoutConfig.totalsData.items

enter image description here

10
  • 2
    How could one add the specific product url to the item-array? This would clarify your already great question even more! – Max Oct 19 '16 at 10:34
  • Hello Khoa, as per your answer i have added short description into window.checkoutConfig.totalsdata and window.checkoutConfig.quoteItemData as well. when we reach checkout page the short description is coming, but when we move to payment or come back to shipping tab it dissapears. any idea ? – Sunil Verma Nov 21 '16 at 12:27
  • 1
    it will work until totals are recalculated on shipping method change etc. The proper way is to use TotalsItemExtensionInterface and add all these via it – c0rewell Jan 24 '17 at 9:21
  • @c0rewell I see, I need to test more. – Khoa TruongDinh Jan 24 '17 at 9:44
  • @Sunil Verma Can you please help me? I need to get the product attribute. – Sejal Shah Jun 9 '17 at 12:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.