Use the Frontend Product Repository

The frontend product repository is a storage service that uses the local cache to get product information without making additional requests to the server. The product information it provides is useful for optimal mini-cart, widgets, and checkout customizations.

This article contains code samples for common tasks when working with the frontend product repository.

The product data storage

The frontend product repository uses the product_data_storage section of the data storage cache as its data source. This section is responsible for holding all product data that come from the server when a customer visits a product page.

Instantiate the repository

The following code snippet uses the Magento_Catalog/js/product/storage/storage-service to initialize the repository when the data storage cache itself initializes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
define([
    'Magento_Catalog/js/product/storage/storage-service'
]), function(storage){
    'use strict';

    return {

        ...

        identifiersConfig: {
            namespace: 'product_data_storage'
        },

        productStorageConfig: {
            namespace: 'product_data_storage',
            customerDataProvider: 'product_data_storage',
            className: 'DataStorage'
        },

        initIdsStorage: function(){
            storage.onStorageInit(this.identifiersConfig.namespace, this.idsStorageHandler.bind(this));
            return this;
        },

        idsStorageHandler: function(idsStorage){
            this.productStorage = storage.createStorage(this.productStorageConfig);
        },

        ...

    }

}

Use the repository

Subscribe a callback function to the product repository data to work with the cached data from recent server requests.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
...

idsStorageHandler: function(idsStorage){
    this.productStorage = storage.createStorage(this.productStorageConfig);
    this.productStorage.data.subscribe(this.dataCollectionHandler.bind(this));
},

dataCollectionHandler: function(data){
    //Code to handle the data
},

...

Get data from the server

Use the loadDataFromServer method from the data-storage class to get product data from a list of IDs.

1
2
3
4
5
6
7
8
9
10
11
...

idsStorageHandler: function(idsStorage, currency, storeId){
    this.productStorage = storage.createStorage(this.productStorageConfig);
    this.productStorage.data.subscribe(this.dataCollectionHandler.bind(this));
    this.productStorage.loadDataFromServer(currency, storeId, idsStorage.get());
},

...

Parameter Description
currency The currency data to get for the product
store The ID of the store associated with the product
ids An object that contains the list of IDs as keys

In the preceding example the data is handled by the subscribed function dataCollectionHandler.

Specify REST resource

Use the following REST endpoint to get product information:

/V1/products-render-info

For UI Components, add this information in the dataProvider entry inside your etc/view/frontend/ui_component/<ui-component-name>.xml file.

The following example is from the recently-viewed widget:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<argument name="dataProvider" xsi:type="configurableObject">
    <argument name="data" xsi:type="array">
        <item name="config" xsi:type="array">
            <item name="productStorageConfig" xsi:type="array">
                <item name="namespace" xsi:type="string">product_data_storage</item>
                <item name="className" xsi:type="string">DataStorage</item>
                <item name="updateRequestConfig" xsi:type="array">
                    <item name="url" xsi:type="serviceUrl" path="/products-render-info"/>
                </item>
            </item>
            <item name="identifiersConfig" xsi:type="array">
              <item name="namespace" xsi:type="string">recently_viewed_product</item>
            </item>
        </item>
    </argument>
</argument>

This sets the appropriate information inside the updateRequestConfig object in the product storage configuration(productStorageConfig in the example code).

The object structure for this REST response is represented by \Magento\Catalog\Api\Data\ProductRenderInterface:

Show Object Structure
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
[
   item_id: {
        //@see: \Magento\Catalog\Api\Data\ProductRender\ButtonInterface
        'add_to_*_button': { //Any product button will be represented by this interface
            post_data: {...},
            required_options: boolean,
            url: string
        },
        //\Magento\Catalog\Api\Data\ProductRenderExtensionInterface
        'extension_attributes': {
            'review_html': '...'
        },
        //@see: \Magento\Catalog\Api\Data\ProductRender\ImageInterface[]
        'images': [
            {
                'url': '...',
                'code': '...',
                'height': ...,
                'width': ...,
                'resized_height': ...,
                ...
            }
        ],
        'is_salable': boolean,
        'name': '...',
        //@see: \Magento\Catalog\Api\Data\ProductRender\PriceInfoInterface
        'price_info': {
            //@see \Magento\Catalog\Api\Data\ProductRender\FormattedPriceInfoInterface
            //All prices are kind of html with currency symbol and rounding rules
            'formatted_prices': {
                'final_price': ...,
                'max_price': ...,
                'max_regular_price': ...,
                'minimal_regular_price': ...,
                ...
            },
            'final_price': ...,
            'max_price': ...,
            'max_regular_price': ...,
            'minimal_regular_price': ...,
            ...
        },
        'url': '...',
        'type': '...', //enum: configurable, simple, virtual, etc
        'currency_code': '...', //e.g. USD
        'store_id': ... //integer
   }
]