On the product page you can use a customer data in js:
require('Magento_Customer/js/customer-data').get('cart')().items
This is a preferred way because if you load that items on the backend (php) it will not work with a full page cache.
Update with example code:
Note: full code available in example module on GitHub
Here is my example based on your code:
Adding block to the product page (for test purposes it will be place just right in the content area)
app/code/MageWorx/CustomProductPage/view/frontend/layout/catalog_product_view.xml
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceContainer name="content">
<block class="Magento\Framework\View\Element\Template"
name="custom.product.info.cart.items"
template="MageWorx_CustomProductPage::cart_items.phtml"/>
</referenceContainer>
</body>
</page>
Creating template with our component and configuration:
app/code/MageWorx/CustomProductPage/view/frontend/templates/cart_items.phtml
<div class="col-md-12" data-bind="scope: 'cart-items-section'" style="padding: 0;" id="cart-items-section">
<!-- ko template: getTemplate() --><!-- /ko -->
</div>
<script type="text/x-magento-init">
{
"*": {
"Magento_Ui/js/core/app": {
"components": {
"cart-items-section": {
"component": "MageWorx_CustomProductPage/js/cart-items"
}
}
}
}
}
</script>
Creating a component itself (.js
part, e.g. MageWorx_CustomProductPage/js/cart-items
):
app/code/MageWorx/CustomProductPage/view/frontend/web/js/cart-items.js
define([
'jquery',
'ko',
'uiComponent',
'Magento_Customer/js/customer-data',
'uiRegistry'
], function ($, ko, Component, customerData, registry) {
'use strict';
return Component.extend({
defaults: {
template: 'MageWorx_CustomProductPage/product/cart-items'
},
observableProperties: [
'items'
],
/** @inheritdoc */
initialize: function () {
this._super();
var self = this;
customerData.get('cart').subscribe(
function (cartData) {
console.log(cartData);
self.items(cartData.items);
}
);
this.items(customerData.get('cart')().items); //get cart items
console.log(this.items());
},
initObservable: function () {
this._super();
this.observe(this.observableProperties);
return this;
}
});
});
Here is some clarifications:
- We use custom template named
MageWorx_CustomProductPage/product/cart-items
to render items.
- We use customer data as a source for items.
- Items property is observable part of our component (see
observableProperties
prop. and initObservable
function), where all items from customer data will be stored.
- Each time when the customer data updated we synchronize our
items
property with the items in cart (see customerData.get('cart').subscribe
part of init
function body).
Adding main template:
app/code/MageWorx/CustomProductPage/view/frontend/web/template/product/cart-items.html
<div style="float: left" data-bind="visible: items().length">
<h3 data-bind="i18n: 'Cart items template'"></h3>
<ul>
<!-- ko foreach: items -->
<li>
<!-- ko template: 'MageWorx_CustomProductPage/product/item' --><!-- /ko -->
</li>
<!-- /ko -->
</ul>
</div>
<div style="float: left" data-bind="visible: !items().length">
<!-- ko i18n: 'There no items in your cart' --><!-- /ko -->
</div>
Adding a sub-template responsible for render of an each item from a cart:
app/code/MageWorx/CustomProductPage/view/frontend/web/template/product/item.html
<h3><!-- ko i18n: 'Item id: ' --><!-- /ko --><!-- ko text: item_id --><!-- /ko --></h3>
<span data-bind="text: product_name"></span>
<img data-bind="attr: {src: product_image.src, alt: product_image.alt}"/>
<span data-bind="html: product_price"></span>
Result with 1 item:
Result when adding second item:
Result when all items removed through mini-cart on same page:
PS: do not forget to remove the console.log()
from code when all will be done.