Como: Agregar un Button usando un Ui Component en Magento 2


Los botones en el admin solían ser una sola línea en Magento 1. En Magento 2, cuando tu página es un Ui Component, agregas un botón a través del componente: lo declaras en el XML y lo respaldas con una pequeña clase PHP que provee su configuración. Al principio se siente como más trabajo, pero en realidad es más limpio porque cada botón se vuelve testeable y reutilizable.

Este post asume que ya tienes un módulo con un formulario admin Ui Component. Si necesitas construir el formulario primero, echa un vistazo a Como: Usar el Form Ui Component.

Declarar los botones en el formulario

Los botones de un formulario viven en su nodo <settings>. Cada uno apunta a una clase que implementa ButtonProviderInterface.

xml
<?xml version="1.0"?>
<!-- app/code/Vendor/Module/view/adminhtml/ui_component/vendor_entity_form.xml -->
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
    <settings>
        <buttons>
            <button name="save" class="Vendor\Module\Block\Adminhtml\Entity\Edit\SaveButton"/>
            <button name="back" class="Vendor\Module\Block\Adminhtml\Entity\Edit\BackButton"/>
        </buttons>
    </settings>
</form>

La clase del botón

Cada clase de botón devuelve un array con su label, clase, orden y, lo más importante, qué hace al hacer clic.

php
<?php
/** app/code/Vendor/Module/Block/Adminhtml/Entity/Edit/BackButton.php */
namespace Vendor\Module\Block\Adminhtml\Entity\Edit;

use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface;
use Magento\Backend\Block\Widget\Context;

class BackButton implements ButtonProviderInterface
{
    /**
     * @var Context
     */
    private $context;

    /**
     * @param Context $context
     */
    public function __construct(Context $context)
    {
        $this->context = $context;
    }

    /**
     * @return array
     */
    public function getButtonData()
    {
        return [
            'label' => __('Back'),
            'on_click' => sprintf("location.href = '%s';", $this->context->getUrl('*/*/')),
            'class' => 'back',
            'sort_order' => 10,
        ];
    }
}
  • on_click es JavaScript plano, muy útil para un redirect simple.
  • Para el botón Save normalmente omites el on_click y en su lugar devuelves un data_attribute con un form-role igual a save, para que envíe el formulario a la manera del Ui Component.

Un botón dentro de un grid (listing)

Si en cambio quieres un botón en la parte superior de un listing, lo agregas en el XML del listing con un container que apunta a un block de botón, la idea es la misma, una pequeña clase provider que devuelve la data del botón.

Despliega el static content del admin y limpia la caché, y tus botones aparecen exactamente donde los declaraste.

Espero que esto ayude.

Si tienes alguna pregunta o conoces una mejor manera de lograr esto, siéntete libre de compartir en los comentarios a continuación.