如何在Magento2的管理员销售订单视图中添加自定义按钮


12

在此处输入图片说明

如何在magento2的销售订单视图中添加自定义按钮,因为某些事件已不再支持插件。

  • 删除了一些事件(必须使用插件代替):
    • adminhtml_widget_container_html_before(在magento 1.x中使用
    • admin_session_user_logout
    • model_config_data_save_before
    • ...

请参阅Magento2更改日志

Answers:


19

到目前为止,我所看到的最干净的解决方案是使用针对“ beforeSetLayout”的插件

这可以针对确切的块,保存当前请求的检查,还可以避免插件位于“ getOrderId”上,在我的情况下,该插件无法使用,因为我需要在插件方法中调用getOrderId。

所以在di.xml中

   <type name="Magento\Sales\Block\Adminhtml\Order\View">
    <plugin name="addMyButton" type="My\Module\Plugin\Block\Adminhtml\Order\View"/>
   </type>

然后在文件My \ Module \ Plugin \ Block \ Adminhtml \ Order \ View.php中

public function beforeSetLayout(\Magento\Sales\Block\Adminhtml\Order\View $view)
{
    $message ='Are you sure you want to do this?';
    $url = '/mymodule/controller/action/id/' . $view->getOrderId();


    $view->addButton(
        'order_myaction',
        [
            'label' => __('My Action'),
            'class' => 'myclass',
            'onclick' => "confirmSetLocation('{$message}', '{$url}')"
        ]
    );


}

像魅力一样工作
劳尔·桑切斯

17

在尝试了许多不同的方法之后,这是我可以找到的唯一可行的解​​决方案,而且不会影响其他模块。我希望看到其他解决方案。

选项1

在Company / Module / etc / adminhtml / di.xml中创建一个插件

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Backend\Block\Widget\Button\Toolbar">
        <plugin name="MagePal_TestBed::pluginBefore" type="MagePal\TestBed\Plugin\PluginBefore" />
    </type>
</config>

然后在Plugin / PluginBefore.php中

namespace MagePal\TestBed\Plugin;

class PluginBefore
{
    public function beforePushButtons(
        \Magento\Backend\Block\Widget\Button\Toolbar\Interceptor $subject,
        \Magento\Framework\View\Element\AbstractBlock $context,
        \Magento\Backend\Block\Widget\Button\ButtonList $buttonList
    ) {

        $this->_request = $context->getRequest();
        if($this->_request->getFullActionName() == 'sales_order_view'){
              $buttonList->add(
                'mybutton',
                ['label' => __('My Button'), 'onclick' => 'setLocation(window.location.href)', 'class' => 'reset'],
                -1
            );
        }

    }
}

选项2

在Company / Module / etc / adminhtml / di.xml中创建一个插件

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="\Magento\Sales\Block\Adminhtml\Order\View">
        <plugin name="MagePal_TestBed::pluginBeforeView" type="MagePal\TestBed\Plugin\PluginBeforeView" />
    </type>
</config>

然后在Plugin / PluginBeforeView.php中

namespace MagePal\TestBed\Plugin;

class PluginBeforeView
{

    public function beforeGetOrderId(\Magento\Sales\Block\Adminhtml\Order\View $subject){
        $subject->addButton(
                'mybutton',
                ['label' => __('My Buttion'), 'onclick' => 'setLocation(window.location.href)', 'class' => 'reset'],
                -1
            );

        return null;
    }

}

查看完整的源代码


@rs我尝试了第二个选项,它会导致错误- Warning: call_user_func_array() expects parameter 2 to be array, object given in D:\new\OpenServer\domains\graffiticaps-m2.loc\vendor\magento\framework\Interception\Interceptor.php on line 144,因为__callPlugin()方法将beforeGetOrderId()返回的方法添加到方法的参数中getOrderId()。\ vendor \ magento \ framework \ Interception \ Interceptor.php [第124行]- $arguments = $beforeResult;。因此,我认为必须返回其他内容,而不是对象,这意味着$ subject
Kate Suykovskaya

1
我只是在Magento 2.0.2上进行了测试...看一下我对选项2的更新...。请参阅github.com/magepal/stackexchange/tree/develop/91071
Renon Stewart

单击此按钮是否可以调用ajax?
nuwaus

@nuwaus ...您可以将'onclick'更改为'onclick =“ processAjax()”“,然后在其中添加ajax函数或其他一些单击jquery绑定
Renon Stewart


9

创建DI文件app/code/YourVendor/YourModule/etc/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <virtualType name="SalesOrderViewWidgetContext" type="\Magento\Backend\Block\Widget\Context">
        <arguments>
            <argument name="buttonList" xsi:type="object">YourVendor\YourModule\Block\Adminhtml\Order\View\ButtonList
            </argument>
        </arguments>
    </virtualType>
    <type name="Magento\Sales\Block\Adminhtml\Order\View">
        <arguments>
            <argument name="context" xsi:type="object">SalesOrderViewWidgetContext</argument>
        </arguments>
    </type>
</config>

我们在这里做的是:

  1. contextOrder\View块中设置自定义参数。该上下文定义为虚拟类型。
  2. 为窗口小部件上下文定义虚拟类型。我们buttonList使用自己的按钮列表类设置自定义参数。

实现您的按钮列表类:

<?php
namespace YourVendor\YourModule\Block\Adminhtml\Order\View;

class ButtonList extends \Magento\Backend\Block\Widget\Button\ButtonList
{
   public function __construct(\Magento\Backend\Block\Widget\Button\ItemFactory $itemFactory)
   {
       parent::__construct($itemFactory);
       $this->add('mybutton', [
           'label' => __('My button label')
       ]);
   }
}

1
谢谢您的解决方案!我认为这是最好,最优雅的。
eInyzant

这看起来不错,优雅且易于理解,但不幸的是它不起作用。在Magento 2.3.4中,在单击订单时会引发错误Exception occurred during order load
Gianni Di Falco

3

这是到目前为止我不使用插件看到的最好的解决方案之一

MagePal / CustomButton / view / adminhtml / layout / sales_order_view.xml

<?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">
    <body>
        <referenceBlock name="sales_order_edit">
            <block class="MagePal\CustomButton\Block\Adminhtml\Order\View\Buttons" name="custom_buttons">
                <action method="addButtons"/>
            </block>
        </referenceBlock>
    </body>
</page>

MagePal / CustomButton / Block / Adminhtml / Order / View / Buttons.php

namespace MagePal\CustomButton\Block\Adminhtml\Order\View;

class Buttons extends \Magento\Sales\Block\Adminhtml\Order\View
{    
    public function __construct(
        \Magento\Backend\Block\Widget\Context $context,
        \Magento\Framework\Registry $registry,
        \Magento\Sales\Model\Config $salesConfig,
        \Magento\Sales\Helper\Reorder $reorderHelper,
        array $data = []
    ) {
        parent::__construct($context, $registry, $salesConfig, $reorderHelper, $data);
    }

    public function addButtons()
    {
        $parentBlock = $this->getParentBlock();

        if(!$parentBlock instanceof \Magento\Backend\Block\Template || !$parentBlock->getOrderId()) {
            return;
        }

        $buttonUrl = $this->_urlBuilder->getUrl(
            'adminhtml/custombutton/new',
            ['order_id' => $parentBlock->getOrderId()]
        );

        $this->getToolbar()->addChild(
              'create_custom_button',
              \Magento\Backend\Block\Widget\Button::class,
              ['label' => __('Custom Button'), 'onclick' => 'setLocation(\'' . $buttonUrl . '\')']
            );
        }
        return $this;
    }

}

adminhtml_sales_order_view.xml应该有一个错误sales_order_view.xml
Zaheerabbas

没有必要public function __construct
Serhii Koval

2

在以下位置创建di.xml

应用/代码/学习/重写销售/etc/di.xml

内容应该是

<?xml version =“ 1.0”?>
<config xmlns:xsi =“ http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation =“ urn:magento:framework:ObjectManager / etc / config.xsd”>
    <type name =“ Magento \ Backend \ Block \ Widget \ Context”>
        <plugin name =“ add_custom_button_sales_veiw” type =“ Learning \ RewriteSales \ Plugin \ Widget \ Context” sortOrder =“ 1” />
    </ type>
</ config>

在机器上创建Context.php

应用/代码/学习/重写销售/插件/小部件/Context.php

内容应该是

命名空间Learning \ RewriteSales \ Plugin \ Widget;


类上下文
{
    公用函数afterGetButtonList(
        \ Magento \ Backend \ Block \ Widget \ Context $ subject,
        $ buttonList
    )
    {
        $ objectManager = \ Magento \ Framework \ App \ ObjectManager :: getInstance();
        $ request = $ objectManager-> get('Magento \ Framework \ App \ Action \ Context')-> getRequest();
        if($ request-> getFullActionName()=='sales_order_view'){
            $ buttonList-> add(
                'custom_button',
                [
                    '标签'=> __('自定义按钮'),
                    'onclick'=>'setLocation(\''。$ this-> getCustomUrl()。'\')',
                    'class'=>'船'
                ]
            );
        }

        返回$ buttonList;
    }

    公共函数getCustomUrl()
    {
        $ objectManager = \ Magento \ Framework \ App \ ObjectManager :: getInstance();
        $ urlManager = $ objectManager-> get('Magento \ Framework \ Url');
        返回$ urlManager-> getUrl('sales / * / custom');
    }
}

清除Magento缓存并运行更新命令

php bin / magento设置:升级

如果我错了,请纠正我,但是到目前为止,从我的所有测试来看,preference类型都等同于magento 1中的重写。因此,只有一个模块可以利用它
Renon Stewart 2015年

是。但是您不能为受保护的功能创建插件。
Sohel Rana 2015年

只需使用插件更新我的答案
Sohel Rana

1
不用加载objectManager,您可以完成$subject->getRequest()->getFullActionName()
Renon Stewart

将其添加到afterGetButtonList函数之前。...受保护的$ urlBuider; 公共函数__construct(\ Magento \ Framework \ UrlInterface $ urlBuilder){$ this-> urlBuilder = $ urlBuilder; }然后在getCustomUrl()函数中仅添加此行.....返回$ this-> urlBuilder-> getUrl('modulename / controllername / methodname',array('parameter'=> parameter_value));
KA9
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.