Jak dodać niestandardowy przycisk do widoku administracyjnego zamówienia sprzedaży w Magento2

13

wprowadź opis zdjęcia tutaj

Jak dodać niestandardowy przycisk do widoku zamówienia sprzedaży w magento2, ponieważ niektóre zdarzenia zostały usunięte na korzyść wtyczek.

  • Usunięto niektóre zdarzenia (zamiast tego należy użyć wtyczek):
    • adminhtml_widget_container_html_before ( użyj w Magento 1.x )
    • admin_session_user_logout
    • model_config_data_save_before
    • ...

Zobacz Dziennik zmian Magento2

Renon Stewart
źródło

Odpowiedzi:

19

Najczystszym rozwiązaniem, jakie do tej pory widziałem, jest użycie wtyczki kierowanej na „beforeSetLayout”

Może to być ukierunkowane na dokładny blok, zapisując czek dla bieżącego żądania, a także pozwala uniknąć wtyczki na „getOrderId”, która w moim przypadku nie mogłaby zostać użyta, ponieważ musiałem wywołać getOrderId w mojej metodzie wtyczki.

Więc to w di.xml

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

A potem to w pliku 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}')"
        ]
    );


}
Chris
źródło
Działało jak urok
Raul Sanchez
17

Po wypróbowaniu wielu różnych sposobów jest to jedyne rozwiązanie, które wydaje mi się, że działa bez wpływu na inne moduły. Chciałbym zobaczyć inne rozwiązania.

opcja 1

Utwórz wtyczkę w 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>

Następnie w 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
            );
        }

    }
}

Opcja 2

Utwórz wtyczkę w 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>

Następnie w 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;
    }

}

Zobacz pełny kod źródłowy

Renon Stewart
źródło
@rs Wypróbowałem drugą opcję, która powoduje błąd - 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 144ponieważ metoda __callPlugin () dodaje, która beforeGetOrderId()metoda zwraca argumenty getOrderId()metody. \ vendor \ magento \ framework \ Interception \ Interceptor.php [linia 124] - $arguments = $beforeResult;. Myślę więc, że trzeba zwrócić coś innego, ale nie przedmiot, co oznacza $ podmiot
Kate Suykovskaya
1
Właśnie testuję
Renon Stewart
Czy jest jakiś sposób na wywołanie ajax po kliknięciu tego przycisku?
nuwaus
@nuwaus ... możesz zmienić 'onclick' na 'onclick = "processAjax ()" ", a następnie dodać tam funkcję ajax lub jakieś inne wiązanie jquery po kliknięciu
Renon Stewart
tutaj jest podobny problem. magento.stackexchange.com/questions/251458/…
Ajwad Syed
9

Utwórz plik 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>

Co robimy tutaj to:

  1. Ustaw niestandardowy contextargument w Order\Viewbloku. Ten kontekst jest zdefiniowany jako typ wirtualny.
  2. Zdefiniuj typ wirtualny dla kontekstu widżetu. Ustawiamy niestandardowy buttonListargument za pomocą naszej własnej klasy listy przycisków.

Zaimplementuj klasę listy przycisków:

<?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')
       ]);
   }
}
dan.kocherga
źródło
1
Dziękuję za to rozwiązanie! Myślę, że to jest najlepsze i najbardziej eleganckie.
eInyzant
Wyglądało to ładnie, elegancko i łatwo zrozumieć, ale niestety nie działa. W Magento 2.3.4 po kliknięciu zamówienia zgłasza błądException occurred during order load
Gianni Di Falco
3

To jedno z najlepszych rozwiązań, jakie do tej pory widziałem bez użycia wtyczek

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

}
Renon Stewart
źródło
Pomyłka adminhtml_sales_order_view.xmlpowinna byćsales_order_view.xml
Zaheerabbas
Nie ma takiej potrzebypublic function __construct
Serhii Koval
2

Utwórz di.xml następującą lokalizację

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

Treść powinna być

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

Utwórz Context.php po pętli

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

Treść powinna być

przestrzeń nazw Nauka \ RewriteSales \ Plugin \ Widget;


Kontekst klasy
{
    funkcja publiczna afterGetButtonList (
        \ Magento \ Backend \ Block \ Widget \ Context $ Temat,
        $ 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 ().' \ ')',
                    „klasa” => „statek”
                ]
            );
        }

        return $ buttonList;
    }

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

Wyczyść pamięć podręczną Magento i uruchom polecenie aktualizacji

konfiguracja php bin / magento: aktualizacja
Sohel Rana
źródło
Popraw mnie, jeśli się mylę, ale ze wszystkich moich dotychczasowych testów preferencetyp jest odpowiednikiem przepisywania w magento 1. Dlatego tylko jeden moduł może z niego skorzystać
Renon Stewart
tak. Ale nie można utworzyć wtyczki dla funkcji chronionej.
Sohel Rana
Po prostu zaktualizuj moją odpowiedź za pomocą wtyczki
Sohel Rana
1
Zamiast ładowania obiektu objectManager mogłeś zrobić$subject->getRequest()->getFullActionName()
Renon Stewart
dodaj to przed funkcją afterGetButtonList ....... chroniony $ urlBuider; funkcja publiczna __construct (\ Magento \ Framework \ UrlInterface $ urlBuilder) {$ this-> urlBuilder = $ urlBuilder; } Następnie w funkcji getCustomUrl () dodaj tylko ten wiersz ..... zwróć $ this-> urlBuilder-> getUrl ('nazwa modulatora / nazwa kontrolera / nazwa metody', tablica ('parametr' => wartość_parametru));
KA9,