Magento2の管理受注ビューにカスタムボタンを追加する方法


12

ここに画像の説明を入力してください

一部のイベントはプラグインの代わりに削除されたため、magento2の注文ビューにカスタムボタンを追加する方法。

  • 一部のイベントを削除しました(代わりにプラグインを使用する必要があります):
    • adminhtml_widget_container_html_before(magento 1.xで使用
    • admin_session_user_logout
    • model_config_data_save_before
    • ...

Magento2変更ログを参照

回答:


18

これまでに見た最もクリーンなソリューションは、「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 2番目のオプションを試しましたが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

ここに同様の問題があります。magento.stackexchange.com/questions/251458/…–
Ajwad Syed

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. カスタムcontext引数をOrder\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 2018

これは見た目がよく、エレガントで、理解しやすいように見えましたが、残念ながら機能しません。Magento 2.3.4では、注文をクリックするとエラーが発生しますException occurred during order load
Gianni Di Falco

3

これは、プラグインを使用せずにこれまでに見た中で最高のソリューションの1つです

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を作成します

app / code / Learning / RewriteSales / 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>

loactionに従ってContext.phpを作成します

app / code / Learning / RewriteSales / Plugin / Widget / Context.php

コンテンツは

名前空間Learning \ RewriteSales \ Plugin \ Widget;


クラスContext
{
    パブリック関数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'、
                [
                    'label' => __( 'Custom Button')、
                    'onclick' => 'setLocation(\' '。$ this-> getCustomUrl()。' \ ')'、
                    'クラス' => '船'
                ]
            );
        }

        $ buttonListを返します。
    }

    パブリック関数getCustomUrl()
    {
        $ objectManager = \ Magento \ Framework \ App \ ObjectManager :: getInstance();
        $ urlManager = $ objectManager-> get( 'Magento \ Framework \ Url');
        $ urlManager-> getUrl( 'sales / * / custom');を返します。
    }
}

Magentoのキャッシュをクリアして更新コマンドを実行する

php bin / magento setup:upgrade

私が間違っている場合は修正してください。ただし、これまでのすべてのテストから、preferenceタイプはmagento 1での書き換えに相当します。したがって、1つのモジュールのみがそれを利用できます
Renon Stewart

はい。ただし、保護された機能のプラグインを作成することはできません。
Sohel Rana、2015

プラグインを使用して回答を更新してください
Sohel Rana

1
ObjectManagerをロードする代わりに、あなたが実行することができました$subject->getRequest()->getFullActionName()
Renon Stewart

これをafterGetButtonList関数の前に追加します....... protected $ urlBuider; パブリック関数__construct(\ Magento \ Framework \ UrlInterface $ urlBuilder){$ this-> urlBuilder = $ urlBuilder; 次に、getCustomUrl()関数でこの行のみを追加します..... return $ this-> urlBuilder-> getUrl( 'modulename / controllername / methodname'、array( 'parameter' => parameter_value));
KA9 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.