Skip to content

widget_menu — Feldtypen

widget_menu im Widget-JSON definiert das Formular, das Redakteure im Pagebuilder-Properties-Panel ausfuellen. Jeder Eintrag beschreibt genau ein Feld — von einzeiligem Text bis zu Sub-Item-Repeatern. Diese Seite listet alle Feldtypen mit Schema und echten Beispielen.

Grundstruktur

Jedes Feld ist ein JSON-Objekt mit mindestens row und type:

json
{
  "row":         "title",
  "type":        "text",
  "placeholder": "Title"
}
FeldPflichtZweck
rowja (ausser items)DB-Spalte in page_row_col_widget — siehe verfuegbare DB-Spalten
typejaFeldtyp — siehe untenstehende Typen
placeholderneinLabel im Properties-Panel
select_valuebei select (DB){table, value, title, options: []}
optionsbei select (statisch)[{id, title}, ...]
menubei itemsSub-Menu-Definition fuer Repeater-Items

Feldtyp-Uebersicht

TypRendert alsDaten-Target
texteinzeiliges Inputpage_row_col_widget.{row}
textareamehrzeiliges Inputpage_row_col_widget.{row}
filemanagerMedia-Picker-Buttonpage_row_col_widget.{row} (JSON mit Media-ID)
select (statisch)Dropdown mit Inline-Optionspage_row_col_widget.{row}
select (DB)Dropdown aus DB-Tabellepage_row_col_widget.{row}
itemsSub-Items-Repeaterpage_widget_item-Tabelle

Formular-Werte werden beim Speichern in die page_row_col_widget-Zeile dieses Widgets geschrieben. Items landen in einer separaten Tabelle (siehe Widget-Items / Repeater).

text — einzeilige Eingabe

Fuer Titel, Links, Slugs, kurze Labels.

json
{"row": "title", "type": "text", "placeholder": "Title"}

Zugriff im Vue-Template: widget.data?.title. Zugriff in getWidgetContent($widget_array): $widget_array['widget_title'].

row: "text" nutzt Key widget_html

Wenn ein Feld "row": "text" hat (z. B. fuer einen HTML-Block), ist der Key in $widget_array widget_html, nicht widget_text. Das Remapping passiert in PageService.php (Key-Name macht die HTML-Content-Semantik der Spalte explizit). Details: getWidgetContent() › Key-Mapping.

textarea — mehrzeilige Eingabe

Fuer laengere Texte, einfache HTML-Blocks, kurze Beschreibungen.

json
{"row": "text", "type": "textarea", "placeholder": "Text / HTML"}

Zugriff: widget.data?.text im Vue-Template, $widget_array['widget_html'] in PHP.

textarea hat keinen Rich-Text-Editor. Fuer CKEditor-Felder im Pagebuilder-Widget-Formular gibt es derzeit kein offizielles Feldtyp-Mapping — Widgets nutzen entweder textarea mit HTML-Freiheit oder laden den CKEditor nicht pro Feld, sondern pro Seite.

filemanager — Bild/Media

Oeffnet den Media Manager als Modal. Der Redakteur waehlt eine Datei, der Widget-Wert wird als JSON [{"id":"123"}] gespeichert.

json
{"row": "image", "type": "filemanager", "placeholder": "Image"}

Aufloesung zur vollen URL passiert in getWidgetContent() via files::loadURL():

php
$current_item['image'] = files::loadURL($dsatz_news['image']);

Im Vue-Template steht dann eine fertige URL unter widget.content.items[0].image. Wer Bilder direkt aus widget.data.image rendern will, muss selbst parsen.

select (statisch)

Dropdown mit fest eincodierten Optionen. Beispiel aus dem Title-Widget (widgetsBase/bootstrap.php):

json
{
  "row":         "subtitle",
  "type":        "select",
  "placeholder": "Typ",
  "value":       "id",
  "title":       "title",
  "options": [
    {"id": "0", "title": "H1"},
    {"id": "1", "title": "H2"},
    {"id": "2", "title": "H3"}
  ]
}
FeldZweck
optionsInline-Array mit Optionen
valueKey des Options-Objekts, der gespeichert wird
titleKey, der im Dropdown angezeigt wird

Legacy-Format

Die statische select-Variante verwendet direkte value/title-Felder auf der Feld-Ebene — ohne select_value-Wrapper. Das ist das Legacy-Format, wird aber vom Widget-Formular noch unterstuetzt und ist fuer inline-Optionen bequem. Fuer DB-Selects nutzt man die neue Variante (siehe unten).

select (DB-basiert)

Dropdown mit Optionen aus einer DB-Tabelle. Der Redakteur sieht title-Werte und der value-Key (z. B. id) wird gespeichert.

json
{
  "row":         "subtitle",
  "type":        "select",
  "placeholder": "Product",
  "select_value": {
    "table":   "s_products",
    "value":   "id",
    "title":   "title",
    "options": []
  }
}
select_value-FeldZweck
tableDB-Tabelle, aus der gelesen wird
valueSpalte, die als Wert gespeichert wird
titleSpalte, die im Dropdown angezeigt wird
optionsMuss leer sein ([]) — wird beim Rendern vom Backend gefuellt

select_value ist Pflicht fuer DB-Selects

Das alte Format mit direkten table/value/title auf Feld-Ebene (ohne select_value-Wrapper) bleibt aus Kompatibilitaetsgruenden unterstuetzt, ist aber deprecated. Fuer neue Widgets immer select_value verwenden.

Im getWidgetContent() kommt der gewaehlte Wert direkt als ID:

php
$productId = (int) $widget_array['widget_subtitle'];
$q = query("SELECT title, price FROM s_products WHERE id = $productId LIMIT 1");

items — Repeater

Fuer Listen gleichartiger Sub-Elemente (FAQ-Eintraege, USP-Icons, Testimonials, Galerie-Bilder). Items leben in der separaten Tabelle page_widget_item mit base_id/language_short-Pattern.

json
{
  "type":        "items",
  "placeholder": "Testimonials",
  "menu": [
    {"row": "title",    "type": "text",        "placeholder": "Name"},
    {"row": "subtitle", "type": "text",        "placeholder": "Position"},
    {"row": "text",     "type": "textarea",    "placeholder": "Quote"},
    {"row": "image",    "type": "filemanager", "placeholder": "Avatar"}
  ]
}
items-FeldZweck
typeimmer "items"
placeholderLabel der Sub-Liste im Properties-Panel
menuArray von Feldtypen — beschreibt die Felder pro Item

items hat kein row — Items landen in page_widget_item, nicht in einer Spalte von page_row_col_widget. Details: Widget-Items / Repeater.

Verfuegbare DB-Spalten

row muss exakt dem Namen einer Spalte in page_row_col_widget entsprechen. Die komplette Liste:

rowTypHaeufig verwendet fuer
titletinytextWidget-Titel, Haupttext
subtitletinytextUntertitel, Select-Wert, Typ
textmediumtextHTML/Text-Inhalt (PHP-Key: widget_html!)
linktinytextURL, Link
imagetinytextBild (Filemanager-JSON)
gallerytinytextGalerie-Daten
logotinytextLogo-Bild
colortinytextFarbe
pricetinytextPreis
sale_statustinytextVerkaufsstatus
locationtinytextOrt
vcardtinytextvCard-Daten
videotinytextVideo-URL
short_texttinytextKurztext
maptinytextKarten-Daten
accordiontinytextAkkordeon-Daten
sliderrevolutiontinytextSlider-Revolution-ID
pagebuildertinytextPagebuilder-Seiten-ID
formtinytextFormular-ID

row mit unbekannter Spalte

Gibt man "row": "myCustomField" an, wird der Wert beim Speichern verworfen — die Spalte existiert nicht in page_row_col_widget. Der Redakteur sieht das Feld zwar im Properties-Panel, der eingegebene Wert verschwindet aber beim naechsten Page-Load. Keine neuen Spalten zu page_row_col_widget hinzufuegen — fuer strukturierte Zusatzdaten stattdessen einen der vorhandenen Slots semantisch umwidmen (z. B. subtitle fuer einen zweiten Textblock) oder ein items-Repeater nutzen.

image2, pname, dateStart, dateEnd existieren nur in page_widget_item

Diese Spalten gibt es nur in der Items-Tabelle, nicht in page_row_col_widget. Verwendung im Top-Level-Widget-Menu fuehrt zu derselben stillen Daten-Drop-Logik wie oben.

Komplettes Widget-Menu — Beispiel

Aus dem titleBanner-Widget oder aehnlich strukturierten Bannern:

json
{
  "widget_title":    "Title Banner",
  "widget_icon":     "icon.png",
  "widget_subtitle": "Banner with title, subtitle and background image",
  "widget_template": "titleBanner",
  "widget_menu": [
    {"row": "title",      "type": "text",        "placeholder": "Title"},
    {"row": "subtitle",   "type": "text",        "placeholder": "Subtitle"},
    {"row": "image",      "type": "filemanager", "placeholder": "Background"},
    {"row": "link",       "type": "text",        "placeholder": "Link URL"},
    {"row": "short_text", "type": "textarea",    "placeholder": "Button label"}
  ]
}

Fuenf Felder, keine Items, keine DB-Selects — ein Standard-Content-Block. Fuer komplexere Widgets (Shop-Listing, E-Learning, Menueditor-Widget) kommt items plus getWidgetContent() dazu.

Haeufige Fehler

Felder ohne row (ausser items)

Jeder Feldtyp ausser items braucht ein row. Fehlt es, speichert das Formular den Wert nirgends — Redakteur tippt, Feld scheint zu funktionieren, beim Reload ist der Wert weg.

select_value vs. Inline-Options verwechseln

  • Statische Options → direkt options: [...] mit value + title auf Feld-Ebene (Legacy-Format, aber ok).
  • DB-Optionsselect_value: {table, value, title, options: []} als Wrapper. Mischform (beide parallel) oder DB-Select ohne select_value schlaegt fehl.

items.menu statt items.widget_menu

Das Sub-Feld bei items heisst menu, nicht widget_menu. Verwechslung fuehrt zu leerem Repeater.

type case-sensitive

"type": "Text" wird nicht als text erkannt — Feldtyp ist kleingeschrieben. Analog fuer alle anderen Typen.

Siehe auch