Magento 2 Experten — Hyvä Theme, Tailwind CSS & SEO aus einer Hand ›

Eigene Toolbar-Buttons für die UI-Component bauen

Eigene Toolbar-Buttons für die UI-Component bauen

~8 Min. Lesezeit Zuletzt aktualisiert am 9. August 2026

Kapitel 9 hat einen minimalen Save-Button gezeigt. Dieses Kapitel vertieft das Button-Muster und ergänzt "Speichern und weiter bearbeiten" sowie "Duplizieren" für das Testimonial-Formular - beide über dieselbe ButtonProviderInterface-Schnittstelle.

ButtonProviderInterface im Detail

Jeder Button ist eine reine Konfigurationsklasse - keine Logik, nur Daten, die beschreiben, wie der Button aussieht und welches JavaScript-Event er beim Klick auslöst:

app/code/Mironsoft/Testimonial/Block/Adminhtml/Testimonial/Edit/SaveAndContinueButton.php
<?php

declare(strict_types=1);

namespace Mironsoft\Testimonial\Block\Adminhtml\Testimonial\Edit;

use Magento\Ui\Component\Control\Container\ToolbarButtonProviderInterface as ButtonProviderInterface;

/**
 * Configures the "Save and Continue Edit" toolbar button.
 */
class SaveAndContinueButton implements ButtonProviderInterface
{
    /**
     * Returns the button configuration array.
     *
     * @return array<string, mixed>
     */
    public function getButtonData(): array
    {
        return [
            'label' => __('Save and Continue Edit'),
            'class' => 'save',
            'data_attribute' => [
                'mage-init' => [
                    'button' => ['event' => 'saveAndContinueEdit'],
                ],
            ],
            'sort_order' => 80,
        ];
    }
}

Das event saveAndContinueEdit ist bereits im JavaScript-Formular-Provider von Magento_Ui fest verdrahtet - es setzt beim Absenden automatisch den Parameter back=edit, genau den Parameter, den der Save-Controller aus Kapitel 12 bereits ausliest.

Duplizieren-Button mit eigenem Controller

class DuplicateButton implements ButtonProviderInterface
{
    public function __construct(private readonly Context $context)
    {
    }

    public function getButtonData(): array
    {
        $id = (int) $this->context->getRequest()->getParam('id');

        if (!$id) {
            return [];
        }

        return [
            'label' => __('Duplicate'),
            'class' => 'duplicate',
            'on_click' => sprintf(
                "location.href = '%s';",
                $this->context->getUrlBuilder()->getUrl(
                    'mironsoft_testimonial/testimonial/duplicate',
                    ['id' => $id]
                )
            ),
            'sort_order' => 40,
        ];
    }
}

Ein leeres Array (bei einem neuen, noch ungespeicherten Datensatz) bedeutet: kein Button - getButtonData() darf leer zurückgeben, um einen Button bedingt komplett auszublenden, ganz ohne extra Sichtbarkeits-Logik in der XML.

Buttons in form.xml registrieren

<settings>
    <buttons>
        <button name="back" class="Mironsoft\Testimonial\Block\Adminhtml\Testimonial\Edit\BackButton"/>
        <button name="delete" class="Mironsoft\Testimonial\Block\Adminhtml\Testimonial\Edit\DeleteButton"/>
        <button name="duplicate" class="Mironsoft\Testimonial\Block\Adminhtml\Testimonial\Edit\DuplicateButton"/>
        <button name="save_and_continue" class="Mironsoft\Testimonial\Block\Adminhtml\Testimonial\Edit\SaveAndContinueButton"/>
        <button name="save" class="Mironsoft\Testimonial\Block\Adminhtml\Testimonial\Edit\SaveButton"/>
    </buttons>
</settings>

Die Anordnung von links nach rechts richtet sich nach sort_order, nicht nach der Reihenfolge im XML - eine niedrige Zahl steht weiter links.

Toolbar-Buttons für den Grid

Die "Neu hinzufügen"-Schaltfläche über dem Grid selbst folgt demselben Muster, wird aber direkt über den Grid-Controller als addButton()-Aufruf registriert, nicht über form.xml - eine kleine, aber häufig übersehene Inkonsistenz zwischen Grid- und Formular-Toolbar in Magento.

Tipp: Für jeden neuen Button lohnt es sich, kurz zu prüfen, ob ein vergleichbares event bereits im JavaScript-Formular-Provider existiert (wie saveAndContinueEdit oben) - oft lässt sich damit ein kompletter eigener Ajax-Aufruf vermeiden.