Як додати спеціальну кнопку до перегляду замовлень на продаж адміністратора в 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.