Magento 2 – Display Custom Module Data Using KnockOut JS

knockoutjsmagento2

I'm learning the knockout js to display in my custom module data. For this, I have tried below code the controller is successfully running, but it's not showing my data.

my code is:

training_index_view.xml

 <?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceContainer name="content">
            <block class="Learning\Training\Block\KnockOut" before="-" cacheable="false" template="Learning_Training::list.phtml">
                <arguments>
                    <argument name="jsLayout" xsi:type="array">
                        <item name="components" xsi:type="array">
                            <item name="knockouts" xsi:type="array">
                                <item name="component" xsi:type="string">Learning_Training/js/view/knockouts</item>
                            </item>
                        </item>
                    </argument>
                </arguments>
            </block>
        </referenceContainer>
    </body>
</page>

Controller\Index\View.php

<?php

namespace Learning\Training\Controller\Index;

class View extends \Magento\Framework\App\Action\Action{


    /**
     * @var \Magento\Framework\View\Result\PageFactory
     */
    protected $resultPageFactory;


    /**
     * Constructor
     *
     * @param \Magento\Framework\App\Action\Context  $context
     * @param \Magento\Framework\View\Result\PageFactory $resultPageFactory
     */
    public function __construct(
        \Magento\Framework\App\Action\Context $context,
        \Magento\Framework\View\Result\PageFactory $resultPageFactory
    )
    {
        $this->resultPageFactory = $resultPageFactory;
        parent::__construct($context);
    }


    /**
     * Execute view action
     *
     * @return \Magento\Framework\Controller\ResultInterface
     */
    public function execute()
    {
        /** @var \Magento\Framework\View\Result\Page $resultPage */
        $resultPage = $this->resultPageFactory->create();
        $resultPage->getConfig()->getTitle()->set('Welcome to Knock Out!..');
        return $resultPage;
    }


}

Block\KnockOut.php

<?php

namespace Learning\Training\Block;

class KnockOut extends \Magento\Framework\View\Element\Template{

    /**
     * @var array|\Magento\Checkout\Block\Checkout\LayoutProcessorInterface[]
     */
    protected $layoutProcessors;

    public function __construct(
        \Magento\Framework\View\Element\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);
    }

}

Training\view\frontend\web\js\view\knockouts.js

    define([
    'jquery',
    'ko',
    'uiComponent',
    'mage/url',
    'mage/storage'
], function ($, ko, Component, urlBuilder,storage) {
    'use strict';

    var knockout = "";

    return Component.extend({

        defaults: {
            template: 'Learning_Training/knockouts'
        },

        initialize: function () {

            this._super();
            this.knockouts();

        },

        knockouts:function(){
            knockout = ko.observable("Welcome to Knockout JS! :)");
           return knockout;
        }

    });

});

Training\view\frontend\web\template\knockouts.html

 <h1 data-bind="text: knockouts"></h1>

Training\view\frontend\templates\list.phtml

 <?php /** @var $block \Learning\Training\Block\KnockOut */ ?>

<!--<h1><!?php /*echo $block->getTitle(); */?></h1>-->

<div id="block-knockouts" data-bind="scope:'knockouts'" class="block">
    <!-- ko template: getTemplate() --><!-- /ko -->
    <script type="text/x-magento-init">
    {
        "#block-knockouts": {
            "Magento_Ui/js/core/app": <?php /* @escapeNotVerified */ echo $block->getJsLayout();?>
        }
    }
</script>
</div>

enter image description here

Is it the correct way? or I went wrong somewhere?

Please through me right direction.

Best Answer

All good your example code except training_index_view.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">
    <body>
        <referenceContainer name="content">
            <block class="Learning\Training\Block\KnockOut" before="-" cacheable="false" template="Learning_Training::list.phtml">
                <arguments>
                    <argument name="jsLayout" xsi:type="array">
                        <item name="components" xsi:type="array">
                            <item name="knockouts" xsi:type="array">
                                <item name="component" xsi:type="string">Learning_Training/js/view/knockout</item>
                            </item>
                        </item>
                    </argument>
                </arguments>
            </block>
        </referenceContainer>
    </body>
</page>

Clear cache. Now you can able to see html content from Training\view\frontend\web\template\knockout.html

[Update]

Added following line for changing h1 text:


knockouts: ko.observable("Welcome to Knockout JS! :)"),
Related Topic