I see I can use custom action handlers for adminhtml grid actions. This is DOM node for action link (HTML):

<a class="action-menu-item"
        data-bind="attr: {href: $action().href}, 
                   text: $action().label, 
                   click: $col.getActionHandler($action())"

I have created additional action in adminhtml grid with callback data (PHP code):

$actions['alert'] = [
    'label' => __('Alert'),
    'callback' => 'function() {alert("Action!")}'

This action is converted into JSON and is loaded to the grid in this format, where "callback" property is a string (JSON):

"alert": {
  "label": "Alert",
  "callback": "function() {alert(\"Action!\")}"

This is Magento parser for action's props (module-ui/view/base/web/js/grid/columns/actions.js). This parser process JSON data and should call action's callback in case of callback is object/array/function (see _getCallback):

getActionHandler: function (action) {
    var index = action.index,
        rowIndex = action.rowIndex;

    if (this.isHandlerRequired(index, rowIndex)) {
        return this.applyAction.bind(this, index, rowIndex);

applyAction: function (actionIndex, rowIndex) {
    var action = this.getAction(rowIndex, actionIndex),
        callback = this._getCallback(action);

    action.confirm ?
        this._confirm(action, callback) :

    return this;

_getCallback: function (action) {
    var args = [action.index, action.recordId, action],
        callback = action.callback;

    if (utils.isObject(callback)) {

        callback = registry.async(callback.provider);
    } else if (_.isArray(callback)) {
        return this._getCallbacks(action);
    } else if (!_.isFunction(callback)) {
        callback = this.defaultCallback.bind(this);

    return function () {
        callback.apply(callback, args);

But callback property is a string, so defaultCallback is used.

How can I use my own action handler in adminhtml grid actions?


1 Answer 1


Update mass-action action in the grid component xml as below:

        <action name="add">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="confirm" xsi:type="array">
                        <item name="title" xsi:type="string" translate="true">Add Data</item>
                        <item name="message" xsi:type="string" translate="true">Add Data ?</item>
                    <item name="type" xsi:type="string">add</item>
                    <item name="label" xsi:type="string" translate="true">Add Data</item>
                    <item name="callback" xsi:type="array">
                        <item name="provider" xsi:type="string">my_form.my_form.field_data</item>
                        <item name="target" xsi:type="string">addData</item>

Here, my_form.my_form.field_data is my form namespace and file name.

field_data is my text field.

Below is my field with custom js component:

<field name="field_data">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="visible" xsi:type="boolean">false</item>
                <item name="component" xsi:type="string">My_Module/js/data</item>
                <item name="dataType" xsi:type="string">text</item>
                <item name="formElement" xsi:type="string">input</item>
                <item name="source" xsi:type="string">my_form_form_data_source</item>
                <item name="label" xsi:type="string" translate="true">Mass Action Data</item>

data.js component file:

    ], function (_, uiRegistry, Abstract) {
    'use strict';

return Abstract.extend({ addData: function (action, data) { var itemsType = data.excludeMode ? 'excluded' : 'selected', selections = {}; selections[itemsType] = data[itemsType]; if (!selections[itemsType].length) { selections[itemsType] = false; } _.extend(selections, data.params || {}); console.log(selections); // you mass action value. } }); });

You can use any component js to handle the callback. I used my field component js and saved the data in the form field.

Your Answer

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

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