Magento 2 – Display Product Collections Using Knockout JS

knockoutjsmagento2product-collection

I am trying to display product collection using knockout js binding. But not working. Please guide me.

Also in Magento2 is require to manually applyBinding when using component.?

Also please anyone know how to pass data from phtml to js file and bind it with function. Its very difficult structure to implement knockout in Magento2. Can't understand what should we do for even simple render using table with template file.

Here is the code I have implemented.

List PHTML Code.

<?php $_productCollection = $block->getLoadedProductCollection(); ?>
<?php
$jsonData = array(array('Name'=>'chandu','Aje'=>25));
?>
<script type="text/x-magento-init">
{
    "*": {
        "Magento_Ui/js/core/app": {
            "components": {
                "example-scope": {
                    "component": "Kite_Boxes/js/productrender",
                    "items": <?php echo json_encode($jsonData); ?>
                }
            }
        }
    }
}
</script>
<div data-bind="scope: 'example-scope'">
    <!-- ko template: getTemplate() --><!-- /ko -->
</div>

Js File is:

define(['ko', 'uiComponent'], function(ko, Component) {
    'use strict';
    return Component.extend({
        defaults: {
            items: 'hello',
            template: 'Kite_Boxes/productrender'
        },
        initialize: function() {
            this._super();
            this.items = ko.observableArray();
             this.setProductData();
            console.log(this.items);
        },
        setProductData: function() {
         var VM = function () {
         this.columnNames = ko.computed(function () {
              if (this.items().length === 0)
                  return [];
              var props = [];
              var obj = this.items()[0];
              for (var name in obj)
                  props.push(name);
              return props;
          });
      };
      var vm = new VM();
      //ko.applyBindings(vm);
        }
    });
});

HTML Template is:

<table>
    <thead>
        <tr data-bind="foreach: columnNames">
            <th><span data-bind="text: $data"></span></th>
        </tr>
    </thead>
    <tbody data-bind="foreach: items">
        <tr data-bind="foreach: $parent.columnNames">
            <td data-bind="text: $parent[$data]"></td>
  </tr>
    </tbody>
</table>

ERROR is::

Uncaught TypeError: Cannot read property 'items' of undefined

Best Answer

Here i got it working

productrender.js

    define(['ko', 'uiComponent'], function(ko, Component) {
    'use strict';
    return Component.extend({
        defaults: {
             template: 'Kite_Boxes/productrender'
        },
        initialize: function(config) {
             this._super();
             this.setProductData(config.items);
        },
        setProductData: function(items) {
         this.columnNames = ko.computed(function () {
              if (items.length === 0)
                  return [];
              var props = [];
              var obj = items[0];
              for (var name in obj)
                  props.push(name);
              return props;
          });
        }
    });
});

productrender.html

<table>
<thead>
    <tr data-bind="foreach: columnNames">
        <th> <span data-bind="text: $data"></span>

        </th>
    </tr>
</thead>
<tbody data-bind="foreach: items">
    <tr data-bind="foreach: $parent.columnNames">
        <td data-bind="text: $parent[$data]"></td>
    </tr>
</tbody>

list.phtml

    <?php $jsonProductData = $block->getProductCollectinJsonData(); ?>
<script type="text/x-magento-init">
{
    "*": {
        "Magento_Ui/js/core/app": {
            "components": {
                "example-scope": {
                    "component": "Kite_Boxes/js/productrender",
                    "items": <?php echo $jsonProductData; ?>
                }
            }
        }
    }
}
</script>
<div data-bind="scope: 'example-scope'">
    <!-- ko template: getTemplate() --><!-- /ko -->
</div>

ProductList.php Block File

    <?php
namespace Kite\Boxes\Block\Rewrite\Product;
use Magento\Catalog\Api\CategoryRepositoryInterface;
use Magento\Framework\Json\Helper\Data as jsondata;
class ListProduct extends \Magento\Catalog\Block\Product\ListProduct
{
    /*protected $jsonHelper;*/

    /*public function __construct(\Magento\Framework\Json\Helper\Data $jsonHelper)
    {
        $this->jsonHelper = $jsonHelper;
    }*/

    public function __construct(
        \Magento\Catalog\Block\Product\Context $context,
        \Magento\Framework\Data\Helper\PostHelper $postDataHelper,
        \Magento\Catalog\Model\Layer\Resolver $layerResolver,
        CategoryRepositoryInterface $categoryRepository,
        \Magento\Framework\Url\Helper\Data $urlHelper,
        array $data = [],
        jsondata $jsonHelper
    ) {
        $this->jsonHelper = $jsonHelper;
        $this->_catalogLayer = $layerResolver->get();
        $this->_postDataHelper = $postDataHelper;
        $this->categoryRepository = $categoryRepository;
        $this->urlHelper = $urlHelper;
        parent::__construct(
            $context,
            $postDataHelper,
            $layerResolver,
            $categoryRepository,
            $urlHelper,
            $data

        );
    }

    public function getProductCollectinJsonData()
    {
        $_productCollection = $this->getLoadedProductCollection()->addTierPriceData();
        $i                  = 0;
        $ProductData        = array();
        foreach ($_productCollection as $product) {
            if ($product->getTypeId() == 'simple') {
                $ProductData[$i]['Product Name'] = $product->getName();
                if ($product->getTierPrice()) {
                    $tierPriceList = $product->getTierPrice();
                    if (count($tierPriceList) > 0) {
                        $ProductData[$i]['1-' . (intval($tierPriceList[0]['price_qty'])) . ' Packs'] = $tierPriceList[0]['price'];
                    }
                    $count = 0;
                    foreach ($tierPriceList as $key => $trList) {
                        if ($count == (count($tierPriceList) - 1)) {
                            $ProductData[$i][intval($trList['price_qty']) . '+ Packs'] = number_format($trList['price'], 2);
                        } else {
                            $ProductData[$i][intval($trList['price_qty'] + 1) . '-' . (intval($tierPriceList[$key + 1]['price_qty'])) . ' Packs'] = number_format($trList['price'], 2);
                        }

                        $count++;
                    }
                }
                $i++;
            }
        }
        return $this->jsonHelper->jsonEncode($ProductData);
    }
}