Come aggiungere un pulsante personalizzato alla vista dell'ordine di vendita amministratore in Magento2


12

inserisci qui la descrizione dell'immagine

Come aggiungere un pulsante personalizzato alla vista degli ordini di vendita in magento2, poiché alcuni degli eventi sono stati rimossi a favore dei plug-in.

  • Rimossi alcuni eventi (al suo posto è necessario utilizzare plugin):
    • adminhtml_widget_container_html_before ( utilizzare in magento 1.x )
    • admin_session_user_logout
    • model_config_data_save_before
    • ...

Vedi il registro delle modifiche di Magento2

Risposte:


19

La soluzione più pulita che ho visto finora è utilizzare un plug-in con targeting "beforeSetLayout"

Questo può indirizzare il blocco esatto, salvando il controllo per la richiesta corrente ed evita anche che il plugin sia su 'getOrderId' che nel mio caso non potrebbe essere usato come avevo bisogno di chiamare getOrderId nel mio metodo plugin.

Quindi questo in di.xml

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

E poi questo nel 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}')"
        ]
    );


}

Ha funzionato come per incanto
Raul Sanchez il

17

Dopo aver provato molti modi diversi, questa è l'unica soluzione che ho trovato che sembra funzionare senza influenzare altri moduli. Mi piacerebbe vedere altre soluzioni.

opzione 1

Crea un plugin in Azienda / Modulo / 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>

Quindi in 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
            );
        }

    }
}

opzione 2

Crea un plugin in Azienda / Modulo / 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>

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

}

Vedi il codice sorgente completo


@rs Ho provato la seconda opzione e causa un errore 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, poiché il metodo __callPlugin () aggiunge quale beforeGetOrderId()metodo restituisce gli argomenti del getOrderId()metodo. \ vendor \ magento \ framework \ Interception \ Interceptor.php [riga 124] - $arguments = $beforeResult;. Quindi penso che ci debba essere restituito altro, ma non oggetto, che significa $ subject
Kate Suykovskaya

1
Ho appena testato su Magento 2.0.2 ... Dai un'occhiata al mio aggiornamento per l'opzione # 2 .... Vedi github.com/magepal/stackexchange/tree/develop/91071
Renon Stewart

C'è un modo per chiamare ajax facendo clic su questo pulsante?
Nuwaus,

@nuwaus ... potresti cambiare 'onclick' in 'onclick = "processAjax ()" "quindi aggiungere la funzione ajax lì o qualche altra associazione jquery click
Renon Stewart


9

Crea 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>

Quello che facciamo qui è:

  1. Imposta l' contextargomento personalizzato nel Order\Viewblocco. Questo contesto è definito come un tipo virtuale.
  2. Definire il tipo virtuale per un contesto di widget. Impostiamo buttonListargomenti personalizzati con la nostra classe di elenchi di pulsanti.

Implementa la tua classe elenco pulsanti:

<?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
Grazie per questa soluzione! Penso che questo sia il migliore e il più elegante.
eInyzant,

Sembrava bello, elegante e facile da capire, ma sfortunatamente non funziona. In Magento 2.3.4 quando si fa clic su un ordine, viene generato un erroreException occurred during order load
Gianni Di Falco,

3

Questa è una delle migliori soluzioni che ho visto finora senza usare plug-in

MagePal / CustomButton / vedere / 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 / blocchi / Adminhtml / ordine / Vista / 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;
    }

}

Ci adminhtml_sales_order_view.xmldovrebbe essere un erroresales_order_view.xml
Zaheerabbas,

Non è necessario inpublic function __construct
Serhii Koval,

2

Crea di.xml seguendo la posizione

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

Il contenuto dovrebbe essere

<? 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>

Crea Context.php seguendo la loaction

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

Il contenuto dovrebbe essere

spazio dei nomi Learning \ RewriteSales \ Plugin \ Widget;


contesto di classe
{
    funzione pubblica 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' => __ ('Pulsante personalizzato'),
                    'onclick' => 'setLocation (\' '. $ this-> getCustomUrl ().' \ ')',
                    'class' => 'ship'
                ]
            );
        }

        return $ buttonList;
    }

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

Svuota la cache Magento ed esegui il comando di aggiornamento

php bin / magento setup: upgrade

Correggimi se sbaglio, ma da tutti i miei test finora il preferencetipo è l'equivalente di riscrivere in magento 1. Quindi solo un modulo può trarne vantaggio
Renon Stewart

sì. Ma non puoi creare plugin per la funzione protetta.
Sohel Rana,

Aggiorna la mia risposta usando il plugin
Sohel Rana,

1
Invece di caricare objectManager avresti potuto fare$subject->getRequest()->getFullActionName()
Renon Stewart il

aggiungilo prima della funzione afterGetButtonList ....... $ $ protetto urlBuider; funzione pubblica __construct (\ Magento \ Framework \ UrlInterface $ urlBuilder) {$ this-> urlBuilder = $ urlBuilder; } Quindi nella funzione getCustomUrl () aggiungi solo questa riga ..... return $ this-> urlBuilder-> getUrl ('modulename / controllername / methodname', array ('parametro' => parametro_valore));
KA9
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.