Magento – Magento 2: target=”_blank” in UI Listing Action Links

javascriptmagento2PHPuicomponent

In Magento 2, you can create "Action" links for your UI grid. Magento itself does this on the CMS Listing Grid here

#File: vendor/magento/module-cms/Ui/Component/Listing/Column/PageActions.php
//...
$item[$name]['edit'] = [
    'href' => $this->urlBuilder->getUrl($this->editUrl, ['page_id' => $item['page_id']]),
    'label' => __('Edit')
];

//...

Is there a way to have these action links open in a new window? (the same way an <a href="..." target="_blank">Link Test</a> would work. I've tried added both a target and window to the array that creates the link, but that doesn't appear to work.

If I look at the source of a rendered link

<a class="action-menu-item" data-bind="
        attr: {
            href: $action().href
        },
        click: $col.getActionHandler($action()),
        text: $action().label" data-repeat-index="0" href="http://google.com">View Log</a>

I see a bunch of modern abstract javascript who's ultimate source is difficult to track down.

The specific question I'd like answered is "how to make action links open in a new window using the provided UI abstractions" (I know I could add my own javascript to the page that handles it, but that seems like a hack solution for something that's so simple in plain old HTML)

A larger question that I'll accepts an answer for is

  1. Where are the action links rendered
  2. Where the javascript source for the $col.getActionHandler... code below

Best Answer

In Magento 2.1.* target _blank is not working

Following file is responsible to render action in admin UI component Grid

vendor/magento/module-ui/view/base/web/templates/grid/cells/actions.html

Change:

attr="href: $action().href" 

to 

attr="target: $col.getTarget($action()), href: $action().href"

For action dropdown change:

 attr="href: $action().href, 'data-action': 'item-' +
 $action().index"

 to

 attr="target: $col.getTarget($action()), href: $action().href, 'data-action': 'item-' + $action().index"

Or replace below code in vendor/magento/module-ui/view/base/web/templates/grid/cells/actions.html:

<a
class="action-menu-item"
if="$col.isSingle($row()._rowIndex)"
repeat="foreach: $col.getVisibleActions($row()._rowIndex), item: '$action'"
click="$col.getActionHandler($action())"
text="$action().label"
attr="href: $action().href"/>

<div class="action-select-wrap" if="$col.isMultiple($row()._rowIndex)" collapsible>
    <button class="action-select" translate="'Select'" toggleCollapsible/>
    <ul class="action-menu" css="_active: $collapsible.opened">
        <li repeat="foreach: $col.getVisibleActions($row()._rowIndex), item: '$action'">
            <a class="action-menu-item" click="$col.getActionHandler($action())" text="$action().label" attr="href: $action().href, 'data-action': 'item-' + $action().index"/>
        </li>
    </ul>
</div>

Replace with below code

<a
    class="action-menu-item"
    if="$col.isSingle($row()._rowIndex)"
    repeat="foreach: $col.getVisibleActions($row()._rowIndex), item: '$action'"
    click="$col.getActionHandler($action())"
    text="$action().label"
    attr="target: $col.getTarget($action()), href: $action().href"/>

<div class="action-select-wrap" if="$col.isMultiple($row()._rowIndex)" collapsible>
    <button class="action-select" translate="'Select'" toggleCollapsible/>
    <ul class="action-menu" css="_active: $collapsible.opened">
        <li repeat="foreach: $col.getVisibleActions($row()._rowIndex), item: '$action'">
            <a class="action-menu-item" click="$col.getActionHandler($action())" text="$action().label" attr="target: $col.getTarget($action()), href: $action().href, 'data-action': 'item-' + $action().index"/>
        </li>
    </ul>
</div>

Add below function to vendor/magento/module-ui/view/base/web/js/grid/columns/actions.js which is already there in Magento 2.2

/**
 * Returns target of action if it's been set.
 *
 * @param {Object} action - Action object.
 * @returns {String}
 */
getTarget: function (action) {
    if (action.target) {
        return action.target;
    }

    return '_self';
},

Now Use : #File: Vendor/Module/Ui/Component/Listing/Column/PageActions.php

//...
$item[$name]['edit'] = [
    'href' => $this->urlBuilder->getUrl($this->editUrl, ['page_id' => $item['page_id']]),
    'target' => '_blank',
    'label' => __('Edit')
];

Now, Target _blank will work for Magento 2.1.* versions