Cara Menambahkan Tombol Kustom ke Admin Lihat Pesanan Penjualan di Magento2


12

masukkan deskripsi gambar di sini

Bagaimana cara menambahkan tombol kustom ke tampilan pesanan penjualan di magento2, karena beberapa acara dihapus dalam mendukung plugin.

  • Menghapus beberapa acara (plugin harus digunakan sebagai gantinya):
    • adminhtml_widget_container_html_before ( digunakan di magento 1.x )
    • admin_session_user_logout
    • model_config_data_save_before
    • ...

Lihat Magento2 Ubah Log

Jawaban:


18

Solusi terbersih yang saya lihat sejauh ini adalah menggunakan plugin yang menargetkan 'beforeSetLayout'

Ini dapat menargetkan blok yang tepat, menyimpan cek untuk permintaan saat ini, dan juga menghindari plugin yang ada di 'getOrderId' yang dalam kasus saya tidak dapat digunakan karena saya perlu memanggil getOrderId dalam metode plugin saya.

Jadi ini di di.xml

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

Dan kemudian ini dalam file 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}')"
        ]
    );


}

Bekerja seperti pesona
Raul Sanchez

17

Setelah mencoba berbagai cara, ini adalah satu-satunya solusi yang dapat saya temukan yang tampaknya berfungsi tanpa mempengaruhi modul lain. Saya akan senang melihat solusi lain.

Pilihan 1

Buat plugin di Perusahaan / Modul / 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>

Kemudian di 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
            );
        }

    }
}

pilihan 2

Buat plugin di Perusahaan / Modul / 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>

Kemudian di 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;
    }

}

Lihat Kode Sumber Lengkap


@rs Saya sudah mencoba opsi ke-2, dan ini menyebabkan kesalahan - 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, karena metode __callPlugin () menambahkan beforeGetOrderId()metode apa yang kembali ke argumen getOrderId()metode. \ vendor \ magento \ framework \ Interception \ Interceptor.php [baris 124] - $arguments = $beforeResult;. Jadi saya pikir harus ada yang dikembalikan, tetapi tidak keberatan, yang berarti $ subjek
Kate Suykovskaya

1
Saya hanya menguji pada Magento 2.0.2 ... Lihatlah pembaruan saya untuk opsi # 2 .... Lihat github.com/magepal/stackexchange/tree/develop/91071
Renon Stewart

Apakah ada cara untuk memanggil ajax dengan mengklik tombol ini?
nuwaus

@nuwaus ... Anda dapat mengubah 'onclick' menjadi 'onclick = "processAjax ()" "lalu menambahkan fungsi ajax di sana atau yang lainnya di penjilidan jquery klik
Renon Stewart


9

Buat file 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>

Apa yang kami lakukan di sini adalah:

  1. Tetapkan contextargumen khusus ke dalam Order\Viewblokir. Konteks ini didefinisikan sebagai tipe virtual.
  2. Tentukan tipe virtual untuk konteks widget. Kami menetapkan buttonListargumen khusus dengan kelas daftar tombol kami sendiri.

Terapkan kelas daftar tombol Anda:

<?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
Terima kasih atas solusi ini! Saya pikir ini yang terbaik dan paling elegan.
eInyzant

Ini terlihat bagus, elegan dan mudah dimengerti tetapi sayangnya tidak berhasil. Di Magento 2.3.4 saat mengklik secara berurutan, ia melakukan kesalahanException occurred during order load
Gianni Di Falco

3

Ini adalah salah satu solusi terbaik yang saya lihat sejauh ini tanpa menggunakan plugin

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;
    }

}

Ada kesalahan dalam adminhtml_sales_order_view.xmlseharusnyasales_order_view.xml
Zaheerabbas

Tidak perlu dipublic function __construct
Serhii Koval

2

Buat di.xml lokasi berikut

app / code / Learning / RewriteSales / etc / di.xml

Konten seharusnya

<? 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 = "Belajar \ RewriteSales \ Plugin \ Widget \ Context" sortOrder = "1" />
    </type>
</config>

Buat Context.php berikut loaction

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

Konten seharusnya

namespace Learning \ RewriteSales \ Plugin \ Widget;


Konteks kelas
{
    fungsi publik afterGetButtonList (
        \ Magento \ Backend \ Block \ Widget \ Konteks $ 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' => __ ('Tombol Kustom'),
                    'onclick' => 'setLocation (\' '. $ this-> getCustomUrl ().' \ ')',
                    'class' => 'ship'
                ]
            );
        }

        kembalikan $ buttonList;
    }

    fungsi publik getCustomUrl ()
    {
        $ objectManager = \ Magento \ Framework \ App \ ObjectManager :: getInstance ();
        $ urlManager = $ objectManager-> get ('Magento \ Framework \ Url');
        return $ urlManager-> getUrl ('sales / * / custom');
    }
}

Hapus cache Magento dan jalankan perintah pembaruan

setup php bin / magento: tingkatkan

Koreksi saya jika saya salah, tetapi dari semua pengujian yang saya lakukan sejauh preferenceini adalah setara dengan menulis ulang di magento 1. Oleh karena itu hanya satu modul yang dapat memanfaatkannya
Renon Stewart

Iya. Tetapi Anda tidak dapat membuat plugin untuk fungsi yang dilindungi.
Sohel Rana

Perbarui saja jawaban saya menggunakan plugin
Sohel Rana

1
Alih-alih memuat objectManager yang bisa Anda lakukan$subject->getRequest()->getFullActionName()
Renon Stewart

tambahkan ini sebelum fungsi afterGetButtonList ....... protected $ urlBuider; fungsi publik __construct (\ Magento \ Framework \ UrlInterface $ urlBuilder) {$ this-> urlBuilder = $ urlBuilder; } Kemudian pada fungsi getCustomUrl () tambahkan baris ini hanya ..... kembalikan $ this-> urlBuilder-> getUrl ('modulename / controllername / methodname', array ('parameter' => parameter_value));
KA9
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.