2

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.

  • Any error are getting in console? Also please dont keep space before click function in your html file in data-bind attribute. – Rakesh Jesadiya Sep 26 '17 at 16:51
  • Please verify path for Learning/Training/view/frontend/web/js and view/frontend/web/template/knockout.html file. – Rakesh Jesadiya Sep 26 '17 at 16:53
  • @RakeshJesadiya Yes above files are the same path. still not getting. – Bojjaiah Sep 27 '17 at 10:06
  • have you create web/template and web/js folder right? – Rakesh Jesadiya Sep 27 '17 at 10:15
  • @RakeshJesadiya Yes, see above thread. that's my code. – Bojjaiah Sep 27 '17 at 10:21
3

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! :)"),
|improve this answer|||||
  • I tried as you suggested but it showing code in frontend. see my thread has updated the code with the screenshot. – Bojjaiah Sep 28 '17 at 7:07
  • 2
    Download file from here -> dropbox.com/s/jnvh7k583a0iehv/knockoutjs.zip?dl=0 – Sohel Rana Sep 28 '17 at 8:28
  • 1
    After setup, URL -> ../stackexchange/index/view – Sohel Rana Sep 28 '17 at 8:28
  • 1
    Yes, now it's working fine. If I want to display simple text to h1 tag (other than this like return the simple text from js to HTML file) how can? Can you have an example plz..? – Bojjaiah Sep 28 '17 at 9:10
  • 1
    Check updated answer. – Sohel Rana Sep 28 '17 at 9:53
2

If you want to use a function for property knockouts instead of a value like ko.observable('Test'), you should edit your component template like this:

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

<h1 data-bind="text: knockouts()"></h1>
|improve this answer|||||
0

In your controller return pass as null,

 public function execute()
    {
        if ($id = $this->getRequest()->getParam('id')) {
            $TList = $this->_trainingFactory->create()->load($id);

            $TData = [
                'training_id' => $TList->getTrainingId(),
                'firstname' => $TList->getFirstName(),
                'lastname' => $TList->getLastName(),
                'email' => $TList->getEmail()
            ];

            return json_encode($TData);
        }
    }

pass return as array of your dynamic data as above.

Update::

pass template as below way,

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

<h1><?php echo $block->getTitle(); ?></h1>
    <div id="knockouts-div" data-bind="scope:'knockouts'">

        <!-- ko template: getTemplate() --><!-- /ko -->
        <script type="text/x-magento-init">
        {
           "#knockouts-div": {
                 "Magento_Ui/js/core/app": {
                     "components": {
                         "knockouts": {
                             "component": "Learning_Training/js/view/knockout"
                         }
                     }
                 }
             }
        }
        </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>
|improve this answer|||||
  • Yes modified the TraineeList controller will call after Get Training List button clicked. HTML code is not showing in the page see my thread screenshot. – Bojjaiah Sep 26 '17 at 13:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.