Hoy me he enfadado con Magento. Otra vez. 🙃
Es como esa relación tóxica que te da alegrías de vez en cuando, pero cuando se pone de “que no”, te amarga la tarde.
Capítulo de hoy en “cosas que deberían ser fáciles pero resultan un auténtico pain-in-the-ass”: añadir un simple botón a un formulario del admin de Magento.
En concreto, a un formulario como este:

Lo peor es que parecía fácil… pero ni ChatGPT, ni Claude, ni la madre de todas las IAs me dieron una solución decente. Todas iban con respuestas rebuscadísimas, cuando la realidad era mucho más simple.
La magia estaba en algo así:
<field name="chat_button"
class="Vendor\Module\Ui\Component\ChatButton"
component="Vendor_Module/js/form/component/chat-button"
template="Magento_Theme/form/button-field" formElement="button">
<settings>
<dataScope>chat_button</dataScope>
</settings>
<formElements>
<button>
<settings>
<title translate="true">Chat</title>
</settings>
</button>
</formElements>
</field>
El problema es que no hay ni un solo ejemplo de esto en un formulario normal. El único sitio donde se usa algo parecido es en la configuración del sistema, que es muy particular y aunque comparta componentes, no es lo mismo… bueno, si estás aquí leyendo esto ya lo sabías 😉.
Bueno, al grano. Además del XML de arriba (que obviamente va en tu formulario, por ejemplo en .../ui_component/mi_form_form.xml
), hay que crear un par de cositas más:
- Un componente JS para que haga algo, porque no solo queremos que adorne la página.
- Una clase PHP que configure el botón.
La clase (sencillita)
La pones en:
app/code/Vendor/Module/Ui/Component/ChatButton.php
<?php
namespace Vendor\Module\Ui\Component;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\View\Element\UiComponent\ContextInterface;
use Magento\Framework\View\Element\UiComponentFactory;
use Magento\Ui\Component\Form\Field;
class ChatButton extends Field
{
/**
* ResetButton constructor
*
* @param ContextInterface $context
* @param UiComponentFactory $uiComponentFactory
* @param \Magento\Framework\View\Element\UiComponentInterface[] $components
* @param array $data
* @param ScopeConfigInterface $scopeConfig
*/
public function __construct(
ContextInterface $context,
UiComponentFactory $uiComponentFactory,
$components,
array $data,
ScopeConfigInterface $scopeConfig
) {
$this->scopeConfig = $scopeConfig;
parent::__construct($context, $uiComponentFactory, $components, $data);
}
/**
* Add js listener to chat button
*
* @return void
* @throws \Magento\Framework\Exception\LocalizedException
*/
public function prepare()
{
parent::prepare();
$this->_data['config']['actions'] = [
[
'actionName' => 'sendChat',
'targetName' => '${ $.name }',
'__disableTmpl' => ['targetName' => false],
//'params' => [
// 'test' => 'text'
//]
]
];
}
}
De aquí lo único que te interesa es el sendChat
del final. Ese será el método del componente JS que se llamará al pulsar el botón. El resto es paja, lo puedes copiar/pegar tal cual.
¿Necesitas pasarle parámetros? Pues para eso está el params
que he dejado comentado justo debajo.
El componente JS (aún más simple)
Lo pones en:
app/code/Vendor/Module/view/adminhtml/web/js/form/component/chat-button.js
/**
* @api
*/
define([
'Magento_Ui/js/form/components/button',
'uiRegistry'
], function (Button, registry) {
'use strict';
return Button.extend({
defaults: {
label: '',
buttonTpl: 'Magento_Theme/form/element/button'
},
sendChat: function () {
console.log('ACTION executed')
}
});
});
Un componente que extiende el button
de Magento y que engancha nuestra función sendChat
. Al pulsarlo, se ejecuta y… magia.
Pues nada, que aquí te lo dejo para que no pierdas una hora discutiendo con Magento como hice yo. 😅
Hey! Qué opinas sobre el artículo?