4

I have created a phtml template and I have hook it up with a custom uiComponent model. Then I use knockout to bind model data into the template.

This is working fine at the moment, the problem is I can't pass data from PHP into the JS module I have created.

This is what I have so far :

My layout.xml file to display the phtml template :

<block class="Vendor\Module\Block\Customer\Form" name="vendor_module_template" template="Vendor_Module::template.phtml">
<arguments>
    <argument name="jsLayout" xsi:type="array">
        <item name="types" xsi:type="array"/>
        <item name="components" xsi:type="array">
            <item name="custom_component" xsi:type="array">
                <item name="component" xsi:type="string">Vendor_Module/js/component</item>
                <item name="config" xsi:type="array">
                    <item name="template" xsi:type="string">path/to/template</item><!-- I can't access this from js -->
                    <item name="var1" xsi:type="string">some-value</item><!-- I can't access this from js -->
                    <item name="var2" xsi:type="string">some-other-value</item><!-- I can't access this from js -->
                </item>
            </item>
        </item>
    </argument>
</arguments>
</block>

Then I have my phtml template :

<div data-block="refer-friend" data-bind="scope: 'custom_component'">
<form style="display: none;" data-bind="visible: true">
    <ul data-bind="foreach: friends, visible: friends().length > 0" class="hidden">
        <li>
            Email
            <input type="text" name="email" data-bind="value: email, disable: isSent" />
        </li>
        <li>
            <p data-bind="if: isSent"><?= __('Sent'); ?></p>
        </li>
        <li>
            <button  data-bind="disable: isSent">
                <!-- ko if: isSent -->
                <!-- ko i18n: 'Re-Send' --><!-- /ko -->
                <!-- /ko -->

                <!-- ko ifnot: isSent -->
                <!-- ko i18n: 'Send' --><!-- /ko -->
                <!-- /ko -->
            </button>
        </li>
    </ul>
</form>
</div>

<script type="text/x-magento-init">
{
    "[data-block='refer-friend']": {
        "Magento_Ui/js/core/app": <?= $block->getJsLayout();?>
    }
}
</script>

And then finally my component.js file

define([
'uiComponent',
'jquery',
'ko',
'underscore'
 ], function (Component, $, ko, _) {
'use strict';

function Friend(data) {
    this.email = ko.observable(data.email);
    this.isSent  = ko.observable(data.isSent);
};

return Component.extend({

    friends: ko.observableArray(),

    /**
     * @override
     */
    initialize: function () {

        console.log(this.options) ;
        this.friends.push(new Friend({email : '[email protected]', isSent : true}));
        this.friends.push(new Friend({email : '[email protected]', isSent : false}));

    },
});
});

This is all working fine except the fact that I can't access the configuration options I set from the layout xml file. How can this be done?

Also, I would like to use a knockout html template, which I have seen in the core that they also set from the layout xml but this is not working either when I try it.

Thanks in advance !

2 Answers 2

1

You were so close, you're just missing this._super(); from the initialize function.

initialize: function () {
    this._super();
    console.log(this.var1);
    this.friends.push(new Friend({email : '[email protected]', isSent : true}));
    this.friends.push(new Friend({email : '[email protected]', isSent : false}));
},

enter image description here

this._super(); will call the same function it's called in but belonging to the parent, so in this case it will call the initialize function of it's parent (probably Component). If we ran it inside a function named test it would call the test function of it's parent component.

To check how to access everything passed through to the component console log this.

2
  • This doesn't work for me. The browser tries to load a "valueTest.js" file. I think somehow the variable data has to be injected into the object returned by $block->getJsLayout()? Jun 26, 2017 at 19:09
  • I've updated my answer, I completely missed the cause!
    – Ben Crook
    Jun 26, 2017 at 20:29
0

I too have struggled with this (and am still struggling with how to set data in my PHP which is passed to my component)...

The answer is... Just below "strict;" wrap your code inside another function:

return function(config) { ... return component.extend({...}); } 

and the values you set in your .xml will be properties of the config object.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.