I have followed this tutorial link
HOW TO USE KNOCKOUT JS ON A MAGENTO 2 FRONTEND PAGE.
Magenest/KnockoutJs/etc/frontend/routes.xml :
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
<router id="standard">
<route id="knockout" frontName="knockout">
<module name="Magenest_KnockoutJs" />
</route>
</router>
</config>
Magenest/KnockoutJs/view/frontend/layout/knockout_test_index.xml :
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column"
xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<head>
<title>Knockout Js Testing Page</title>
</head>
<body>
<referenceBlock name="content">
<block class="Magenest\KnockoutJs\Block\Test" name="knockoutjs_test_block" template="test.phtml">
<arguments>
<argument name="jsLayout" xsi:type="array">
<item name="components" xsi:type="array">
<item name="test" xsi:type="array">
<item name="component" xsi:type="string">Magenest_KnockoutJs/js/view/test</item>
<item name="displayArea" xsi:type="string">test</item>
</item>
</item>
</argument>
</arguments>
</block>
</referenceBlock>
</body>
</page>
Magenest/KnockoutJs/Block/Test.php :
<?php
namespace Magenest\KnockoutJs\Block;
use Magento\Framework\View\Element\Template;
class Test extends Template
{
/**
* @var array|\Magento\Checkout\Block\Checkout\LayoutProcessorInterface[]
*/
protected $layoutProcessors;
public function __construct(
Template\Context $context,
array $layoutProcessors = [],
array $data = []
) {
parent::__construct($context, $data);
$this->jsLayout = isset($data['jsLayout']) && is_array($data['jsLayout']) ? $data['jsLayout'] : [];
$this->layoutProcessors = $layoutProcessors;
}
public function getJsLayout()
{
foreach ($this->layoutProcessors as $processor) {
$this->jsLayout = $processor->process($this->jsLayout);
}
return \Zend_Json::encode($this->jsLayout);
}
}
Magenest/KnockoutJs/Controller/Test/Index.php :
<?php
namespace Magenest\KnockoutJs\Controller\Test;
class Index extends \Magento\Framework\App\Action\Action
{
protected $resultPageFactory;
public function __construct(
\Magento\Framework\App\Action\Context $context,
\Magento\Framework\View\Result\PageFactory $resultPageFactory
)
{
$this->resultPageFactory = $resultPageFactory;
parent::__construct($context);
}
public function execute()
{
$resultPage = $this->resultPageFactory->create();
return $resultPage;
}
}
Magenest/KnockoutJs/view/frontend/templates/test.phtml :
<div id="test-div" data-bind="scope:'test'">
<!-- ko template: getTemplate() --><!-- /ko -->
<script type="text/x-magento-init">
{
"#test-div": {
"Magento_Ui/js/core/app": <?php /* @escapeNotVerified */ echo $block->getJsLayout();?>
}
}
</script>
<script>
require([
'mage/url',
'Magento_Ui/js/block-loader'
], function(url, blockLoader) {
blockLoader("<?php /* @escapeNotVerified */ echo $block->getViewFileUrl('images/loader-1.gif'); ?>");
return url.setBaseUrl('<?php /* @escapeNotVerified */ echo $block->getBaseUrl();?>');
})
</script>
</div>
Magenest/KnockoutJs/view/frontend/web/js/view/test.js :
define([
'ko',
'uiComponent',
'mage/url',
'mage/storage',
], function (ko, Component, urlBuilder,storage) {
'use strict';
var id=1;
return Component.extend({
defaults: {
template: 'Magenest_KnockoutJs/test',
},
productList: ko.observableArray([]),
getProduct: function () {
var self = this;
var serviceUrl = urlBuilder.build('knockout/test/product?id='+id);
id ++;
return storage.post(
serviceUrl,
''
).done(
function (response) {
self.productList.push(JSON.parse(response));
}
).fail(
function (response) {
alert(response);
}
);
},
});
});
Magenest/KnockoutJs/view/frontend/web/template/test.html :
<button data-bind=" click: getProduct">Get Next Product</button>
<table>
<thead>
<tr>
<th>ID</th>
<th>Product Name</th>
<th>Product Price</th>
<th>Preview</th>
</tr>
</thead>
<tbody data-bind="foreach: productList">
<tr>
<td data-bind="text: entity_id"></td>
<td data-bind="text: name"></td>
<td data-bind="text: price"></td>
<td><img data-bind="attr: {src: src}" width="120" height="150" alt="Product Image"></td>
</tr>
</tbody>
</table>
Magenest\KnockoutJs\Controller\Test\Product.php :
<?php
namespace Magenest\KnockoutJs\Controller\Test;
use Magento\Catalog\Model\ProductFactory;
use Magento\Catalog\Helper\Image;
use Magento\Store\Model\StoreManager;
class Product extends \Magento\Framework\App\Action\Action
{
protected $productFactory;
protected $imageHelper;
protected $listProduct;
protected $_storeManager;
public function __construct(
\Magento\Framework\App\Action\Context $context,
\Magento\Framework\Data\Form\FormKey $formKey,
ProductFactory $productFactory,
StoreManager $storeManager,
Image $imageHelper
)
{
$this->productFactory = $productFactory;
$this->imageHelper = $imageHelper;
$this->_storeManager = $storeManager;
parent::__construct($context);
}
public function getCollection()
{
return $this->productFactory->create()
->getCollection()
->addAttributeToSelect('*')
->setPageSize(5)
->setCurPage(1);
}
public function execute()
{
if ($id = $this->getRequest()->getParam('id')) {
$product = $this->productFactory->create()->load($id);
$productData = [
'entity_id' => $product->getId(),
'name' => $product->getName(),
'price' => '$' . $product->getPrice(),
'src' => $this->imageHelper->init($product, 'product_base_image')->getUrl(),
];
echo json_encode($productData);
return;
}
}
}
But Getting "404"
Complete Module Here