3

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 !

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 : '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.

  • 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()? – Adam Nemitoff Jun 26 '17 at 19:09
  • I've updated my answer, I completely missed the cause! – Ben Crook Jun 26 '17 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, privacy policy and cookie policy

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