Widget-Parameter und Admin-Konfiguration (widget.xml)
Widget-Parameter und Admin-Konfiguration (widget.xml)
~7 Min. Lesezeit Zuletzt aktualisiert am 9. August 2026
Das Widget aus Kapitel 56 funktioniert, ist aber fest verdrahtet: Tier-Badge immer an, keine Möglichkeit für eine Redakteurin, es an das Design der jeweiligen Seite anzupassen. Dieses Kapitel macht genau das im Admin konfigurierbar.
Parameter-Typen im Überblick
text/textarea- freies Texteingabefeld, z. B. für zusätzliche CSS-Klassen.select/multiselect- Dropdown mit fest definierten<option>-Werten, typischerweise auch für Ja/Nein-Schalter genutzt (kein eigenerboolean-Typ nötig).block- ein Auswahldialog ("Chooser"), mit dem eine Redakteurin einen bestehenden CMS-Block auswählt, statt eine ID von Hand zu tippen.url- Link-Auswahldialog, identisch zum URL-Feld in Page Builder.date- Datepicker, z. B. für zeitlich befristete Werbeaktionen.
widget.xml mit zwei echten Parametern
<?xml version="1.0"?>
<widgets xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Widget:etc/widget.xsd">
<widget id="mironsoft_loyalty_points_balance"
class="Mironsoft\Loyalty\Model\Widget\PointsBalanceWidget"
is_email_compatible="false">
<label translate="true">Loyalty: My Points Balance</label>
<description translate="true">Displays the logged-in customer's points balance and loyalty tier.</description>
<parameters>
<parameter name="show_tier_badge" xsi:type="select" visible="true" required="false" sort_order="10">
<label translate="true">Show Loyalty Tier Badge</label>
<options>
<option name="yes" value="1" selected="true">
<label translate="true">Yes</label>
</option>
<option name="no" value="0">
<label translate="true">No</label>
</option>
</options>
</parameter>
<parameter name="css_class" xsi:type="text" visible="true" required="false" sort_order="20">
<label translate="true">Additional CSS Classes</label>
</parameter>
</parameters>
</widget>
</widgets>Die Widget-Klasse liest die Parameter
<?php
declare(strict_types=1);
namespace Mironsoft\Loyalty\Model\Widget;
use Magento\Framework\View\Element\Template;
use Magento\Framework\View\Element\Template\Context;
use Magento\Widget\Block\BlockInterface;
use Mironsoft\Loyalty\ViewModel\PointsBalance;
/**
* Renders the "My Points" widget insertable into any CMS WYSIWYG content. Delegates all
* business logic to ViewModel\PointsBalance (chapter 48); the two getters added in this
* chapter (getShowTierBadge()/getCssClass()) expose only admin-configured presentation
* parameters that have no equivalent on the view model itself.
*/
class PointsBalanceWidget extends Template implements BlockInterface
{
/**
* @param Context $context Framework template context, required by the parent Template class.
* @param PointsBalance $pointsBalanceViewModel Same view model already used in chapters 48/51/52 - reused unmodified here.
* @param array<string, mixed> $data Additional block data, populated by Magento's widget system from the admin-configured parameters below.
*/
public function __construct(
Context $context,
private readonly PointsBalance $pointsBalanceViewModel,
array $data = [],
) {
parent::__construct($context, $data);
$this->setTemplate('Mironsoft_Loyalty::widget/points-balance-widget.phtml');
}
/**
* Returns the injected view model.
*
* @return PointsBalance
*/
public function getViewModel(): PointsBalance
{
return $this->pointsBalanceViewModel;
}
/**
* Whether the tier badge should render, defaulting to true when the admin left the
* parameter unset (e.g. a widget instance saved before this parameter existed).
*
* @return bool
*/
public function getShowTierBadge(): bool
{
$value = $this->getData('show_tier_badge');
return $value === null || (bool) $value;
}
/**
* Returns any additional CSS classes configured in the admin, empty string if none.
*
* @return string
*/
public function getCssClass(): string
{
return (string) ($this->getData('css_class') ?? '');
}
}Achtung: Ab hier zeigt $this->setTemplate() auf eine NEUE Datei, widget/points-balance-widget.phtml, statt weiter widget/points-balance.phtml aus Kapitel 53 zu nutzen. Grund: Magento\Framework\View\Element\AbstractBlock erbt von \Magento\Framework\DataObject und damit dieselbe __call()-Magie, die Kapitel 49 bereits bei AbstractModel::getData() erklärt hat - auch der generische Template-Block aus Kapitel 51/52 würde also $block->getShowTierBadge() klaglos entgegennehmen, nur eben immer mit null statt echtem Default. Ein und dieselbe Template-Datei über zwei Kontexte hinweg unterschiedliches, stillschweigendes Verhalten zeigen zu lassen wäre genau die Art unnötiger Kopplung, vor der Kapitel 49 bereits gewarnt hat - deshalb sauber getrennt, sobald die Template-Verträge tatsächlich auseinanderlaufen.
<?php
declare(strict_types=1);
use Magento\Framework\Escaper;
use Mironsoft\Loyalty\Model\Widget\PointsBalanceWidget;
use Mironsoft\Loyalty\ViewModel\PointsBalance;
/**
* @var PointsBalanceWidget $block
* @var Escaper $escaper
*/
/** @var PointsBalance $viewModel */
$viewModel = $block->getViewModel();
?>
<?php if ($viewModel->canShow()): ?>
<div class="my-4 rounded-xl border border-gray-200 bg-white p-4 shadow-sm sm:p-6 <?= $escaper->escapeHtmlAttr($block->getCssClass()) ?>">
<dl class="flex flex-col gap-1 sm:flex-row sm:items-baseline sm:justify-between">
<div>
<dt class="text-sm font-medium text-gray-500">
<?= $escaper->escapeHtml(__('Your points balance')) ?>
</dt>
<dd class="text-3xl font-bold tracking-tight text-gray-900">
<?= $escaper->escapeHtml($viewModel->getFormattedPointsBalance()) ?>
</dd>
</div>
<?php if ($block->getShowTierBadge()): ?>
<span class="inline-flex w-fit items-center rounded-full bg-amber-100 px-3 py-1 text-sm font-semibold capitalize text-amber-800">
<?= $escaper->escapeHtml($viewModel->getTier()) ?>
</span>
<?php endif; ?>
</dl>
</div>
<?php endif; ?>Admin-Konfiguration in der Praxis
- Content > Elements > Widgets > "Add Widget" - Widget-Typ "Loyalty: My Points Balance" wählen.
- Design-Theme und Store-View-Zuordnung festlegen (die Standard-Widget-Instance-Felder, für jedes Widget gleich).
- Tab "Widget Options":
show_tier_badgeundcss_classerscheinen automatisch als Formularfelder - generiert direkt auswidget.xml, kein eigenes Admin-Formular nötig. - Tab "Layout Updates": Seite oder Container festlegen, wo das Widget erscheinen soll - erzeugt intern die Layout-XML-Aktualisierung aus Kapitel 55.
Alternativ: direkt im WYSIWYG-Editor einer beliebigen CMS-Seite auf "Widget einfügen" klicken - derselbe Parameter-Dialog erscheint dort als Modal, das Ergebnis landet als {{widget type="Mironsoft\Loyalty\Model\Widget\PointsBalanceWidget" show_tier_badge="1"}}-Direktive direkt im Seiteninhalt, ganz ohne gespeicherte Widget Instance.
Tipp: Nach jeder widget.xml-Änderung: bin/cache-clean config. Nach jeder Template-Änderung reicht bin/cache-clean block_html - beide Cache-Typen unabhängig voneinander, wie schon in den vorherigen Blöcken dieser Serie.
Achtung: css_class und show_tier_badge sind rein präsentational - sie ändern nichts an der in Kapitel 56 beschriebenen Full-Page-Cache-Gefahr bei kundenspezifischen Widgets auf öffentlichen Seiten. Diese Warnung gilt unverändert, egal welche Parameter im Admin gesetzt sind.