Knockout JS is a Javascript library using MVVM ( Model-View-ViewModel ) pattern to bind data with DOM elements. It is widely used in Magento 2, where implementations often include a ViewModel in javascript and an HTML template bound to the viewmodel.

In this article, we will go through the steps to create component on product details page. We will use KnockoutJS in Magento 2 to :

  • Get feedback data from 3rd party API
  • Get data template
  • Async display component data on product details page
Create the layout for product details page
<!--File: view/frontend/layout/catalog_product_view.xml -->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="product.info.main">
            <block class="Netmatter\RezdyIntegration\Block\Catalog\Product\View"
                   name="product.info.availability"
                   before="product.info.map"
                   template="Netmatter_RezdyIntegration::catalog/product/availability.phtml" cacheable="false" />
        </referenceBlock>
    </body>
</page>

    

Create the file availability.phtml . Here we bind a scope called ‘availability-block’ and declare a component. KnockoutJS will handle this component and display the result on this template

		<?php /* File: view/frontend/templates/catalog/product/availability.phtml */ ?>
<?php $_helper = $this->helper('Netmatter\RezdyIntegration\Helper\RezdyApi'); ?>
<?php if ($_helper->isEnabled()): ?>
  <div id="product-rzd-availability" data-bind="scope: 'availability-block'">
     <!-- ko template: getTemplate() --> <!-- /ko -->
  </div>  
 
  <script type="text/x-magento-init">    
     {    
         "#product-rzd-availability": {  
             "Magento_Ui/js/core/app": { 
                 "components": {         
                     "availability-block": {
                         "component": "Netmatter_RezdyIntegration\/js\/view\/product-rzd-availability",
                         "sku": "<?php /* @escapeNotVerified */ echo $block->getProductSku(); ?>"
                     }
                 }
             }
         }
     }    
  </script>
<?php endif; ?>
	

Before we can write the component, we need to write the block for this template, to get product data and pass to the component.

Step 4: File block

Using this block, we get the product SKU and return to the component:

<?php 
// File: Block/Catalog/Product/View.php 

namespace Netmatter\RezdyIntegration\Block\Catalog\Product;
          
use Magento\Catalog\Block\Product\Context;
use Magento\Catalog\Block\Product\AbstractProduct;
use Magento\Catalog\Helper\Data;
                   
class View extends AbstractProduct       
{   
    public function __construct(
        Context $context,                
        array $data
    ) {   
        parent::__construct($context, $data);
    }     
 
    public function getProductSku() {    
        return $this->getProduct()->getSku();
    }     
}
	

Step 5: Component

Our component using Magento 2 KnockoutJS to process data:

/* File: view/frontend/web/js/view/product-rzd-availability.js */
define([
   'uiComponent', 
   'ko',
   'jquery',
], function(uiComponent, ko, $) {        
   'use strict';
 
   return uiComponent.extend({
       defaults: {
           template: 'Netmatter_RezdyIntegration/product-rzd-availability'
       }, 
 
 
       initialize: function (config) {   
            var selft = this;            
            
            self.availability = ko.observable();
 
            $.ajax({
                url: '/netmatter_rezdyintegration/product/checkavailability/sku/' + config.sku + '/',
                type: 'get',             
                dataType: 'json',        
                context: this,           
                success: function(resp) {
                    self.availability(resp.data);
                }
            });
 
           this._super();
       }  
   });    
});       
		

Template file:

<!-- File: view/frontend/web/template/product-rzd-availability.html -->
<div class="list-availability" data-bind="foreach: { data: availability, as: 'data' }">
               <div class="date-line">
                   <div class="label">Available from:</div>
                   <div class="date-text" data-bind="text: data.startTimeLocal"></div>
               </div>
</div>    
		

Here’s a breakdown of the component and template file we’ve made:

First, the component file needs to have a template assigned. This template will be used when we call getTempalte() from .phtml file:

       defaults: {
           template: 'Netmatter_RezdyIntegration/product-rzd-availability'
       }, 
	

We also create a function storing required variables and parameters for the component:

            var selft = this;            
            
            self.availability = ko.observable();
	
15 years experience of work with e-commerce projects as an contractor