Як додати спеціальну кнопку до перегляду замовлень на продаж адміністратора в Magento2


13

введіть тут опис зображення

Як додати спеціальну кнопку до перегляду замовлень на продаж у magento2, оскільки деякі події було видалено на користь плагінів.

  • Видалено деякі події (замість них потрібно використовувати плагіни):

Див. Журнал змін Magento2

Відповіді:


19

Найчистіше рішення, яке я бачив до цього часу, - це використовувати плагін, орієнтований на "ранішеSetLayout"

Це може орієнтуватися на точний блок, зберігаючи чек для поточного запиту, а також уникає того, що плагін буде на '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

Створіть плагін у компанії / модулі / тощо / 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

Створіть плагін у компанії / модулі / тощо / 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 \ Перехоплення \ Interceptor.php [рядок 124] - $arguments = $beforeResult;. Тому я думаю, що треба повернути щось інше, але не об’єкт, тобто $ subject
— Катя Суйковська

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/…
— Айвад

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

Це виглядало приємно, елегантно і легко зрозуміти, але, на жаль, це не працює. У Magento 2.3.4 при натисканні на замовлення він видає помилкуException occurred during order load
— Gianni Di Falco

4

Це одне з найкращих рішень, які я бачив досі без використання плагінів

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
— Захерабас

Немає потреби вpublic function __construct
— Сергій Коваль

2

Створіть наступне розташування di.xml

app / code / Навчання / RewriteSales / тощо / di.xml

Зміст має бути

<? xml version = "1.0"?>
<config xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi: noNamespaceSchemaLocation = "урна: magento: Framework: ObjectManager / etc / config.xsd">
    <type name = "Magento \ Backend \ Block \ Widget \ Context">
        <plugin name = "add_custom_button_sales_veiw" type = "Навчання \ RewriteSales \ Plugin \ Widget \ Context" sortOrder = "1" />
    </type>
</config>

Створіть Context.php після наступної реакції

app / code / Навчання / RewriteSales / Плагін / Віджет / Context.php

Зміст має бути

Навчання простору імен \ 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-> додати (
                'custom_button',
                [
                    'label' => __ ('Спеціальна кнопка'),
                    'onclick' => 'setLocation (\' '. $ this-> getCustomUrl ().' \ ')',
                    'class' => 'корабель'
                ]
            );
        }

        повернути $ buttonList;
    }

    публічна функція getCustomUrl ()
    {
        $ objectManager = \ Magento \ Framework \ App \ ObjectManager :: getInstance ();
        $ urlManager = $ objectManager-> get ('Magento \ Framework \ Url');
        повернути $ urlManager-> getUrl ('продаж / * / звичай');
    }
}

Очистіть кеш Magento та запустіть команду оновлення

Налаштування php bin / magento: оновлення

Виправте мене, якщо я помиляюсь, але, з усіх моїх тестувань, до цих пір preferenceтип є еквівалентом переписати в magento 1. Тому цим може скористатися лише один модуль
— Renon Stewart

так. Але ви не можете створити плагін для захищеної функції.
— Сохель Рана

Просто оновіть мою відповідь за допомогою плагіна
— Sohel Rana

1
Замість завантаження objectManager ви могли це зробити$subject->getRequest()->getFullActionName()
— Renon Stewart

додайте це перед функцією afterGetButtonList ....... захищено $ urlBuider; публічна функція __construct (\ Magento \ Framework \ UrlInterface $ urlBuilder) {$ this-> urlBuilder = $ urlBuilder; } Потім у функції getCustomUrl () додайте лише цей рядок ..... поверніть $ this-> urlBuilder-> getUrl ('ім'я модуля / ім'я контролера / ім'я методу', масив ('параметр' => параметр_значення));
— KA9
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.