I've been struggling with that for days... For an admin extension, I'm trying to load an uiComponent with Ajax to be displayed in a tab. The uiComponent is correctly loaded but seems not to be fully processed by client-side knockout logic.
namespace Man4x\MondialRelay2\Block\Adminhtml\Shipping;
class Tabs
extends \Magento\Backend\Block\Widget\Tabs {
protected function _construct()
{
parent::_construct();
$this->setId('mondialrelay2_shipping_tabs');
$this->setDestElementId('container');
$this->setTitle(__('MondialRelay'));
}
protected function _beforeToHtml()
{
$this->addTab(
'mass_shipping',
[
'label' => __('Mass Shipping'),
'title' => __('Mass Shipping'),
'url' => $this->getUrl('*/*/massshipping', ['_current' => true]),
'class' => 'ajax'
]
);
return parent::_beforeToHtml();
}
}
Here is the simple controller layout:
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<container name="root" label="Root">
<uiComponent name="mondialrelay2_massshipping_grid"/>
</container>
Note: this custom uiComponent is perfectly functional when loaded in a standard (i.e. non-AJAX) way
When tracking out AJAX response, I can see the correct HTML code for the uiComponent is loaded (included the Magento specific "x-magento-init" tag). It's then processed by the jquery-ui callback:
this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
// support: jQuery <1.8
// jQuery <1.8 returns false if the request is canceled in beforeSend,
// but as of 1.8, $.ajax() always returns a jqXHR object.
if ( this.xhr && this.xhr.statusText !== "canceled" ) {
tab.addClass( "ui-tabs-loading" );
panel.attr( "aria-busy", "true" );
this.xhr
.success(function( response ) {
// support: jQuery <1.8
// http://bugs.jquery.com/ticket/11778
setTimeout(function() {
panel.html( response );
that._trigger( "load", event, eventData );
}, 1 );
})
...for loaded HTML code to be inserted in the container tag. Then, a bunch of callbacks and hooks are processed in the js modules jungle. A "contentUpdated" event is finally triggered, causing the:
/**
* Init components inside of dynamically updated elements
*/
$('body').on('contentUpdated', function () {
if (mage) {
mage.apply();
}
});
return $.mage;
}));
mage/apply/main.js and mage/apply/scripts.js are then correctly called (as tracked down in the browser console) but... nothing happens. My loaded
<script type="x-magento-init">
disappeared but my component JS logic doesn't process at all.
Any enlightenment would be highly appreciated.
PS: after deeper investigation, it seems that component JS files of the uiComponent are actually loaded, but not their templates !
I encountered the same problem you did in a similar scenario. It seems like the bindings are not applied as they should, or at least not when they should, in this scenario. To fix it without altering the template i resorted to some additional xml, in your case this could be:
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<container name="root" label="Root" htmlTag="div" htmlId="mondialrelay2">
<uiComponent name="mondialrelay2_massshipping_grid"/>
<block class="Magento\Framework\View\Element\Text" name="ajax_ui_component_fix">
<action method="setText">
<argument name="text" xsi:type="string"><![CDATA[<script>
require(['jquery'], function ($) {
$('#mondialrelay2').applyBindings();
});
</script>]]></argument>
</action>
</block>
</container>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With