Magento – How to pass data from PHP to a custom uiComponent js class

knockoutjsmagento2uicomponent

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 : 'friend1@example.com', isSent : true}));
        this.friends.push(new Friend({email : 'friend2@example.com', 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 !

Best Answer

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 : 'friend1@example.com', isSent : true}));
    this.friends.push(new Friend({email : 'friend2@example.com', 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.