Suppose I have a custom table and some fields like entity_id, code, title, description and image_path. And I require that I want to show a drop-down (key=>value) on the custom page where some options will be shown and based on that selected option I want to show the records using knockout. whenever the user changes the value from the dropdown then the records from the database will be shown below. The dropdown key will match with the table code column, which will be used to filter records. If there are any questions, feel free to ask in the comments. Any Idea Thanks.
2 Answers
Create a block and call your model inside your block. Here is example :
app/code/Vendor/Module/Block/CustomData.php
namespace Vendor\Module\Block;
use Magento\Framework\View\Element\Template;
use Vendor\Module\Model\ResourceModel\CustomModel\CollectionFactory;
class CustomData extends Template
{
protected $collectionFactory;
public function __construct(
Template\Context $context,
CollectionFactory $collectionFactory,
array $data = []
) {
$this->collectionFactory = $collectionFactory;
parent::__construct($context, $data);
}
public function getCustomData()
{
$collection = $this->collectionFactory->create();
return $collection->getItems();
}
}
Then create your knockoutjs component file and call html template in your js
app/code/Vendor/Module/view/frontend/web/js/view/custom-component.js
define([
'uiComponent',
'ko',
'jquery'
], function (Component, ko, $) {
'use strict';
return Component.extend({
defaults: {
template: 'Vendor_Module/custom-component'
},
initialize: function () {
this._super();
this.customData = ko.observableArray([]);
this.loadCustomData();
},
loadCustomData: function () {
var self = this;
$.ajax({
url: '/rest/V1/custommodule/customdata',
type: 'GET',
success: function (data) {
self.customData(data);
}
});
}
});
});
Now Create a template for your KnockoutJS component:
app/code/Vendor/Module/view/frontend/web/template/custom-component.html
<div data-bind="foreach: customData">
<div>
<h2 data-bind="text: name"></h2>
<p data-bind="text: description"></p>
</div>
</div>
Create layout XML to include your KnockoutJS component
app/code/Vendor/Module/view/frontend/layout/default.xml
<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="Vendor\Module\Block\CustomData" name="custom_data_block">
<arguments>
<argument name="jsLayout" xsi:type="array">
<item name="components" xsi:type="array">
<item name="customComponent" xsi:type="array">
<item name="component" xsi:type="string">Vendor_Module/js/view/custom-component</item>
</item>
</item>
</argument>
</arguments>
</block>
</referenceContainer>
</body>
</page>
follow these steps:
1. Create a Custom Table
Create your custom table with fields: entity_id, code, title, description, and image_path.
2. Create a Model and Resource Model
Define a model and resource model for your custom table.
Model: app/code/Vendor/Module/Model/CustomTable.php
<?php
namespace Vendor\Module\Model;
use Magento\Framework\Model\AbstractModel;
class CustomTable extends AbstractModel
{
protected function _construct()
{
$this->_init('Vendor\Module\Model\ResourceModel\CustomTable');
}
}
Resource Model: app/code/Vendor/Module/Model/ResourceModel/CustomTable.php
<?php
namespace Vendor\Module\Model\ResourceModel;
use Magento\Framework\Model\ResourceModel\Db\AbstractDb;
class CustomTable extends AbstractDb
{
protected function _construct()
{
$this->_init('custom_table', 'entity_id');
}
}
3. Create a Collection
Collection: app/code/Vendor/Module/Model/ResourceModel/CustomTable/Collection.php
<?php
namespace Vendor\Module\Model\ResourceModel\CustomTable;
use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection;
class Collection extends AbstractCollection
{
protected $_idFieldName = 'entity_id';
protected $_eventPrefix = 'custom_table_collection';
protected $_eventObject = 'custom_table_collection';
protected function _construct()
{
$this->_init('Vendor\Module\Model\CustomTable', 'Vendor\Module\Model\ResourceModel\CustomTable');
}
}
4. Create a Block
Create a block to fetch data from the custom table and pass it to the template.
Block: app/code/Vendor/Module/Block/Custom.php
<?php
namespace Vendor\Module\Block;
use Magento\Framework\View\Element\Template;
use Vendor\Module\Model\ResourceModel\CustomTable\CollectionFactory;
class Custom extends Template
{
protected $collectionFactory;
public function __construct(
Template\Context $context,
CollectionFactory $collectionFactory,
array $data = []
) {
$this->collectionFactory = $collectionFactory;
parent::__construct($context, $data);
}
public function getCustomTableData()
{
$collection = $this->collectionFactory->create();
return $collection->getItems();
}
}
5. Create a Template
Create a template to display the dropdown and data.
Template: app/code/Vendor/Module/view/frontend/templates/custom.phtml
<div id="custom-table-data" data-bind="with: customTableDataViewModel">
<select data-bind="options: options, value: selectedOption"></select>
<div data-bind="foreach: filteredItems">
<div>
<p data-bind="text: title"></p>
<p data-bind="text: description"></p>
<img data-bind="attr: { src: image_path }" />
</div>
</div>
</div>
6. Create a ViewModel
ViewModel: app/code/Vendor/Module/view/frontend/web/js/view/custom-table-data.js
define([
'ko',
'jquery',
'uiComponent'
], function (ko, $, Component) {
'use strict';
return Component.extend({
defaults: {
template: 'Vendor_Module/custom-table-data'
},
initialize: function () {
this._super();
var self = this;
self.options = ko.observableArray([]);
self.selectedOption = ko.observable();
self.items = ko.observableArray([]);
self.filteredItems = ko.computed(function () {
return ko.utils.arrayFilter(self.items(), function (item) {
return item.code === self.selectedOption();
});
});
$.ajax({
url: 'path_to_your_controller',
type: 'GET',
success: function (data) {
self.items(data);
var codes = data.map(function (item) { return item.code; });
self.options(codes);
}
});
}
});
});
7. Update Layout
Layout: app/code/Vendor/Module/view/frontend/layout/default.xml
<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="Vendor\Module\Block\Custom" name="custom_table_data" template="Vendor_Module::custom.phtml" />
</referenceContainer>
</body>
</page>
8. Create a Controller
Controller: app/code/Vendor/Module/Controller/Index/Custom.php
<?php
namespace Vendor\Module\Controller\Index;
use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Vendor\Module\Model\ResourceModel\CustomTable\CollectionFactory;
use Magento\Framework\Controller\Result\JsonFactory;
class Custom extends Action
{
protected $collectionFactory;
protected $resultJsonFactory;
public function __construct(
Context $context,
CollectionFactory $collectionFactory,
JsonFactory $resultJsonFactory
) {
$this->collectionFactory = $collectionFactory;
$this->resultJsonFactory = $resultJsonFactory;
parent::__construct($context);
}
public function execute()
{
$collection = $this->collectionFactory->create();
$items = [];
foreach ($collection as $item) {
$items[] = $item->getData();
}
$result = $this->resultJsonFactory->create();
return $result->setData($items);
}
}
9. Run Setup Upgrade
Run the following commands:
php bin/magento setup:upgrade
php bin/magento setup:di:compile
php bin/magento setup:static-content:deploy -f
php bin/magento cache:flush