Skip to content

Pagebuilder-Widgets

Ein Widget ist ein vorkonfiguriertes Frontend-Element, das Redakteure im Visual Pagebuilder auf Seiten platzieren. Widgets liefern eigene Vue-Komponenten fuers Rendering, ein Admin-Formular-Menu und optional einen PHP-Datenlader fuer dynamische Inhalte. Diese Seite erklaert das Konzept und grenzt es zu Admin-Plugins ab.

Widget vs. Admin-Plugin

AspektAdmin-PluginPagebuilder-Widget
WasModul im Backend-MenueBaustein fuer Pagebuilder-Seiten
Verzeichnis_public/extensions/core/backend/{plugin}/_public/extensions/core/backend/{plugin}/widgets/{widget}/
Klasse{plugin}_BackendPlugin extends install_controller{widget}_PageBuilderPlugin (keine Vererbung)
Registrierung$this->content_construct + $this->apiEndpoints$this->pagebuilder_widgets als JSON-Array
FrontendOptional (Admin-layout/index.vue)Pflicht (template/index.vue)
Lebt inplugin_backend-Tabellepage_widgets-Tabelle

Ein Plugin kann beides gleichzeitig anbieten — z. B. einen Admin-Bereich zum Verwalten von Testimonials plus ein Widget, das diese im Frontend anzeigt. Siehe Plugin-Anatomie und das Beispiel unten.

Wozu Widgets bauen?

Use CaseBeispiel
Wiederkehrender Content-BlockTitel-Banner, USP-Iconliste, Testimonial
Integration einer DatenquelleBlog-Preview, Produkt-Teaser, Instagram-Feed
Visuelles Element ohne DBSpacer, Button, Image-Overlay-Text
Komplette SubseiteShop-Checkout, User-Center, 3D-Exhibition
FormulareNewsletter-Anmeldung, Custom-Form

Das CMS liefert bereits ~42 Widgets mit (siehe Widget-Katalog unten). Eigene Widgets fuegen sich nahtlos in den gleichen Picker ein.

Widget-Lebenszyklus

1. install()           # Plugin setzt $this->pagebuilder_widgets = [JSON...]
   → Eintrag in page_widgets (Widget-Registry) pro Widget-Typ

2. vueRegistry-Rebuild # /admin/cache oder Cache-Rebuild
   → Scan aller widgets/*/template/index.vue
   → Generierung von plugin-registry.js pro Theme

3. Picker im Pagebuilder  # WidgetPickerModal.vue
   → Liest page_widgets, zeigt widget_title + widget_icon + widget_subtitle

4. Redakteur zieht Widget auf Seite
   → Zeile in page_row_col_widget (DB)

5. Modal-Formular rendert widget_menu-Felder
   → Admin-User befuellt Felder → PATCH /api/backend/pagebuilder

6. Frontend-Rendering (PageService)
   → Widget-Array wird an PagebuilderWidget.vue uebergeben
   → getWidgetContent() laedt ggf. dynamische Daten (PHP)
   → plugin-registry.js loest widget_template → Vue-Komponente
   → Komponente bekommt { data, content } als widget-Prop

Registrierung in bootstrap.php des Plugins

Die eigentliche Widget-Registrierung geschieht im Plugin — nicht in der Widget-Ordner-eigenen bootstrap.php. Beispiel aus widgetsBase:

php
// widgetsBase/bootstrap.php (Ausschnitt aus install())
$this->pagebuilder_widgets = [
    '{
        "widget_title":    "Title",
        "widget_icon":     "icon.png",
        "widget_subtitle": "Insert a title (H1-H6)",
        "widget_template": "title",
        "widget_menu": [
            {"row": "title",    "type": "text",   "placeholder": "Title"},
            {"row": "subtitle", "type": "select", "placeholder": "Typ",
             "value": "id", "title": "title",
             "options": [
                {"id": "0", "title": "H1"},
                {"id": "1", "title": "H2"},
                {"id": "2", "title": "H3"}
             ]}
        ]
    }',
    '{
        "widget_title":    "Text / HTML",
        "widget_icon":     "icon.png",
        "widget_template": "html",
        "widget_menu": [
            {"row": "text", "type": "textarea", "placeholder": "Text / HTML"}
        ]
    }'
];

Jeder Eintrag ist ein JSON-String mit mindestens widget_title, widget_icon, widget_template und widget_menu. Details zum Feldtypen-Schema siehe Widget-Menu-Feldtypen.

Nach Aenderungen am Array: Plugin de-/reinstallieren oder manuell in page_widgets updaten. Nach Aenderungen an template/index.vue: vueRegistry-Rebuild unter /admin/cache.

Datenbank-Tabellen

TabelleZweck
page_widgetsWidget-Registry (ein Eintrag pro Widget-Typ, aus $this->pagebuilder_widgets)
page_row_col_widgetPlatzierte Widget-Instanzen pro Seite (mit Spalten wie title, subtitle, text, image, …)
page_widget_itemItems fuer Repeater-Widgets (Sub-Datensaetze mit base_id/language_short)

Spalten von page_row_col_widget entsprechen direkt den moeglichen row-Werten im widget_menu. Details: Widget-Menu-Feldtypen › DB-Spalten.

Widget-Katalog

Eingebaute Widgets nach Plugin:

PluginWidgets
widgetsBasetitle, html, image, footer_links, social_footer, pagebuilder_element
spacer / button / imageButton / imageOverlayTextje ein Widget
titleBanner / titleBannerElementBanner-Elemente
infoBoxes / uspIconList / instagramJourney / locationMap / jobs / galleryContent-Listen mit Items
blogblog, blogpreview
emailmarketingnewsletter
productListingproductListing
shopproductTeaser, categoryBannerNoLink, newReleasesNoLink, user, shop, checkout, abobutton, calendar
shopware6sw6ProductListing, sw6ProductDetail, sw6Cart, sw6Checkout, sw6UserAccount, sw6CategoryTeaser, sw6SearchBar
elasticsearchelasticsearch, searchbar
elearningelearning
exhibitionexhibition
pagebuilderform

Insgesamt ~42 Widgets. Die vollstaendige Feld-Definitions-Referenz liegt im Skill pagebuilder-widgets (references/widget-catalog.md im Repo).

shop/widgets/email ist kein Pagebuilder-Widget

Der Ordner _public/extensions/core/backend/shop/widgets/email/ liegt aus Legacy-Gruenden unter widgets/, ist aber kein Picker-Widget — es handelt sich um ein PHPMailer-basiertes Template fuer Auftrags-Bestaetigungsmails. Analog: der menueditor registriert keine Pagebuilder-Widgets (reines Admin-Plugin mit content_construct=template).

Minimal-Widget

Der schnellste Weg zu einem funktionierenden Widget:

_public/extensions/core/backend/{plugin}/
└── widgets/
    └── helloWidget/
        ├── bootstrap.php
        ├── icon.png
        └── template/
            └── index.vue
php
// bootstrap.php
<?php
class helloWidget_PageBuilderPlugin
{
    public static function getVersion() { return "1.0.0"; }
    public static function getName()    { return "Hello Widget"; }

    public static function getWidgetContent($widget_array, $backend = false)
    {
        return null;   // keine dynamischen Daten
    }
}
vue
<!-- template/index.vue -->
<template>
  <div class="hello-widget">
    <h2>{{ widget.data?.title || 'Hello!' }}</h2>
  </div>
</template>

<script setup lang="ts">
defineProps<{ widget: { data?: Record<string, any>; content?: any } }>()
</script>

Die Registrierung liegt in der bootstrap.php des Plugins (nicht in diesem Widget-Ordner). Vollstaendiges Copy-Paste-Beispiel siehe Testimonial-Widget.

Siehe auch

Version 1.0.0 — Impressum