Magento 2 : Run/Execute Javascript after KnockoutJS has rendered all elements

Because Magento use async rendering it not possible to make what you ask.

But you can work with js UI component to disable field

require(['uiRegistry'], function (uiRegistry) {
    uiRegistry.get("product_form.product_form.product-details.quantity_and_stock_status_qty.qty", function (element) {
        element.disable()
    })
})

This answer is correct, however we're lacking information regarding how we know to use 'product_form.product_form.product-details.quanityt_and_stock_status_qty.qty' as the get() parameter.

.get is looking for its first parameter to be a component. So... how do you find the component, and is that language clear? No.

As an example, I wanted to add some custom javascript functionality to the customer information page within the Magento 2 admin. Specifically under, editing a user, 'Account Information' tab.

There are two ways to approach this from what I can tell...

Edit the datasource, to change values. Manipulate the field, such as visibility.

Edit the datasource:

Lets roll. Some dots are missing here, but we're on a page handled by the magento customer module, its an edit page... so we look here... /vendor/module-customer/view/adminhtml/layout/customer_index_edit.xml. Within here the content area is defined to contain 'customer_form'.

<referenceContainer name="content">
    <uiComponent name="customer_form"/>
</referenceContainer>

This means we're looking for a 'customer_form.xml' file, in this case it is found under /vendor/module-customer/view/base/ui_component/customer_form.xml. Within here we find the definition for a couple of the forms within the tabs and their fields. The datasource we're after is defined near the top.

<argument name="data" xsi:type="array">
    <item name="js_config" xsi:type="array">
        <item name="provider" xsi:type="string">customer_form.customer_form_data_source</item>
    </item>
    <item name="label" xsi:type="string" translate="true">Customer Information</item>
    <item name="reverseMetadataMerge" xsi:type="boolean">true</item>
</argument>

Note the 'provider' of 'customer_form.customer_form_data_source'. This is where all of our field data will exist within the .get call.

Our .get() would now become:

uiRegistry.get('customer_form.customer_form_data_source', function(element) {
    console.log(element.data);
});

Now, the question becomes... what can we do with this- and all you can do is adjust the data. You can turn fields true/false, manipulate values, so on. Useful.

Manipulate the field:

What if we want to hide the field and only show it under x condition... we can't do that with the datasource.

Now... this is going to be long and seem convoluted. Its because I'm teaching how to find your data... as I don't know how to find this any other way- and its going to be different per module. Teach a man to fish.

First I output my 'customer_form.customer_form_data_source' within our .get(). This will provide us a 'params' object key, within that is the definition of an 'activeArea' on the object, which is 'customer_form.areas.customer_edit_tab_view_content'.

Ok... so there are 'areas'. Areas, are the tabs on the left- each one is an area. Open up the '_elems' within your console, you'll notice 9 objects at the top. Open the second one and you'll find a label of 'Account Information'. This is the section I'm after. Then observe the 'name' value of 'customer_form.areas.customer'... ok lets try that as our get() param.

uiRegistry.get('customer_form.areas.customer', function(element) {
    console.log(element);
});

This is our fieldset wrapper, check its name value within the console under '_elems'->0->'name'. 'customer_form.areas.customer.customer'... we're drilling down. We're actually already there, check the 'name' value on the field you want to edit. You'll notice its name is 'customer[field_name]'. Making our path for get() is 'customer_form.areas.customer.customer.['field_name]'.

uiRegistry.get('customer_form.areas.customer.customer.[field_name]', function(element) {
    element.visible(false);
});

Examples: [form_name].[tab_areas].[area_name].[fieldset_name].[field_name] customer_form.areas.customer.customer.field_name


There is a plugin built into Require JS to handle page load, this is the preferred method as any other modules that depend on yours will also be aware of the page load requirement. If you use the jQuery method mentioned by Rajeev the other modules will not be aware of the page load requirement.

The plugin is called domReady! and can be used by adding it as a dependency like so:

require(["jquery", "domReady!"], function($){
    // Your code here
});

This will wait for page load but doesn't necessarily mean it loads after all other KO modules as they may also be waiting for page load. For that reason I think KAndy's method is the most reliable, but this answer may help others.


The document ready or DOM loaded events won't be fired on completion of UI form loading.

Here, either you shall have to write a function in javascript which should be called at some interval and as soon as your target element appears in DOM, process your business logic and clear the interval.

Another option could be - to execute your JavaScript business logic after completion of AJAX request which can be achieved using following code block.

$(document).ajaxComplete(function() {
// enter your code here
});