Module HTML-Templates Geschätzte Lektüre: 12 Minuten Einleitung Die Limbas Formular-/Bericht-Editoren sind eine gute Möglichkeit, Formulare oder Berichte per Drag&Drop pixel-genau zu entwerfen. Einzelne Elemente wie bspw. Fließtext oder Dateninhalte sind dabei jedoch voneinander getrennt und ließen sich bisher nur vom Administrator mit Php-Skripten miteinander kombinieren. Für Newsletter, Anschreiben, Rechnungen etc. ist es jedoch oft notwendig, Dateninhalte wie Kunden-Namen oder Preise direkt in den Fließtext zu integrieren. Seit Version 3.6 ist dies durch die neue Html-Template-Engine in Limbas komfortabel mit dem Wysiwyg-Editor möglich. Ansicht im Wysiwyg-Editor (Daten-Platzhalter in blau) Ergebnis im Bericht Funktionsweise In das neue Template-Element im Formular-/Berichts-Editor kann normaler Text geschrieben werden, aber auch direkt Html. Die Besonderheit im Vergleich zum Textblock-Element ist, dass das Template-Element verschiedene Platzhalter im Text erkennt, welche von der Template-Engine für den Nutzer automatisch ersetzt werden. So können beispielsweise Dateninhalte eingebunden werden. Oft werden manche Texte, wie bspw. Firmendaten, in mehreren Berichten benutzt und sollen nicht in jedem Bericht erneut eingegeben werden. Die Template-Engine erlaubt dafür einen modularen Aufbau der Formulare/Berichte: Textbausteine können in einer eigenen Tabelle des Typs Berichtsvorlagen definiert werden und mit einem Unter-Template-Element-Platzhalter in andere Template-Elemente eingebunden werden. Die Tabelle muss beim Erstellen des Template-Elements ausgewählt werden. Es ergibt Sinn, den Berichts-Inhalt in einem Datensatz name dieser Tabelle zu definieren und diesen im Template-Element des Berichtseditors zu referenzieren: ${name} Platzhalter-Syntax Es gibt zwei Möglichkeiten, Platzhalter einzufügen: Entweder mit der ${...}-Syntax oder als ein <lmb /> Html-Element. In den folgenden Beispielen werden immer beide (äquivalenten) Varianten gezeigt. Platzhalter können im Wysiwyg-Editor auch über das „Limbas Templates“-Kontextmenü eingefügt werden. Im Hintergrund wird dabei die <lmb />-Variante eingefügt. ${Einleitung} // bzw <lmb type="template" name="Einleitung" />// (wird immer angezeigt) ${form: Einleitung} // bzw <lmb type="template" name="Einleitung" target="form" />// (wird nur im Formular angezeigt) ${report: Einleitung} // bzw <lmb type="template" name="Einleitung" target="report" />// (wird nur im Bericht angezeigt) Nach der Öffnungsklammer bzw. als „target“-Attribut kann optional ein Medium (form/report) angegeben werden, für welchen das Element angezeigt werden soll. Ist kein Medium angegeben wird es für alle Medien angezeigt. Dateninhalt Daten-Platzhalter im Wysiwyg-Editor ${->Name} // bzw <lmb type="data" src="->Name" /> Erkennbar an dem Pfeil (->). Hier wird beispielsweise der Inhalt des Feldes Name eingefügt. Die Daten kommen dabei aus dem Datensatz, für den das Formular geöffnet bzw. für den der Bericht gedruckt wird. ${=>Auftraege->Name} // bzw <lmb type="data" src="=>Auftraege->Name" /> Die Tabelle ist dabei implizit durch den Datensatz angegeben, man kann sie für mehr Übersichtlichkeit aber auch explizit mit dem Doppelpfeil (=>) angeben. Um Felder einer 1:1-verknüpften Tabelle abzufragen kann die gleiche Syntax verwendet werden. ${->Kunde->Name} // bzw <lmb type="data" src="->Kunde->Name" /> Es werden auch Verknüpfungsfelder unterstützt. Das obere Beispiel zeigt beispielsweise den Namen des verknüpften Kunden an. Kunde ist hierbei der Name des Verknüpfungsfeldes der aktuellen Tabelle. ${->Kunde->Name|"Kein Kunde verknüpft!"} // bzw <lmb type="data" src="->Kunde->Name" alt="Kein Kunde verknüpft!" /> Es kann auch ein Defaultwert angegeben werden für den Fall, dass im Datensatz für das Feld kein Wert eingetragen ist. ${->Name[key=value]} ${->Name[flag]} // bzw <lmb type="data" src="->Name" data-key="value" /> <lmb type="data" src="->Name" data-flag /> In eckigen Klammern können weitere Optionen übergeben werden. Diese werden je nach Medium (Formular / Bericht) unterschiedlich unterstützt/gehandhabt. ${->Name} // => "Alfred" ${->Name[show=description]} // => "Vorname" ${->Name[show=title]} // => "Vorname des Kunden" // bzw <lmb type="data" src="->Name" data-show="description" /> // => "Vorname" // etc Des Weiteren kann statt der Daten auch die Beschreibung bzw. der Titel des Feldes angezeigt werden (Siehe Tabellenfeld-Einstellungen). Vordefinierte Optionen Für verschiedene Feldtypen gibt es vordefinierte Optionen. keyvalueBeschreibungFeldtypwtrueFormularelement ist schreibbar (nur Formular)allenotitletrueAusblenden des Titels bei Auswahlfeldern (nur Formular)Auswahlpool Checkbox/Radiowidth[Numeric]Breite der Zelle bis zum Titel eines Auswahlfeldes (nur Formular)Auswahlpool Checkbox/Radiouse_specificID [Numeric]Anzeigen eines einzelnes Checkbox / Radio Elements aus Pool. Wert-ID aus PooleintragAuswahlpool Checkbox/Radiolinebreak‚line‘ / userdefined [string]Umbruch einzelner Checkbox / Radio Elemente aus Pool. default: break; ohne Umbruch: „line“; benutzdefiniertes ZeichenAuswahlpool Checkbox/Radiopositionleft / rightAusrichtung von Checkbox / Radio Elementen zum TitelAuswahlpool Checkbox/Radiocode_uncheckedCODE [Numeric]Fontzeichen einzelner Checkbox / Radio Elemente aus Pool . (UTF-8 HTML Entity decimal) default: 9675 / 9744Auswahlpool Checkbox/Radiocode_checkedCODE [Numeric]Fontzeichen einzelner ausgewählter Checkbox / Radio Elemente aus Pool. (UTF-8 HTML Entity decimal) default: 9679 / 9746Auswahlpool Checkbox/Radio Unter-Element-Optionen im Wysiwyg-Editor Unter-Element Unter-Element-Platzhalter im Wysiwyg-Editor ${Einleitung} // bzw <lmb type="template" name="Einleitung" /> Anstelle dieses Platzhalters wird beispielsweise die Berichtsvorlage mit dem Namen Einleitung eingefügt. Der Name einer Berichtsvorlage muss eindeutig sein. Die Berichtsvorlagen-Tabelle kann aber auch so gefiltert werden (bspw. nach Sprache des angemeldeten Nutzers), dass der Name bei der Auswertung eindeutig ist. Dynamische Dateninhalte Siehe Berichte. Template-Gruppen Siehe Berichte. Funktionsaufruf Funktions-Platzhalter im Wysiwyg-Editor (Funktion „anredeText“ mit 3 Parametern) ${=FunktionsName()} // bzw <lmb type="func" name="FunktionsName" /> Erkennbar an dem Gleichheitszeichen (=). Der Server wertet bei Berichten die Funktion report_FunktionsName aus, bei Formularen die Funktion form_FunktionsName. Diese kann in den Skript-Erweiterungen implementiert sein. Das report_-/form_-Präfix sorgt dafür, dass keine Systemfunktionen direkt aufgerufen werden können. An die Funktion können beliebig viele Parameter übergeben werden (getrennt durch Komma). Die Anzahl der übergebenen Parameter sollte dabei mit der Anzahl der Parameter der implementierten Funktion übereinstimmen um Fehler zu vermeiden. Es gibt dabei 4 Typen von Parametern: Texte ${=FunktionsName("Ein beliebiger String")} // bzw <lmb type="func" name="FunktionsName"><lmb type="value" value="Ein beliebiger String" /></lmb> Zahlen ${=FunktionsName(-42.5)} // bzw <lmb type="func" name="FunktionsName"><lmb type="value" value="-42.5" /></lmb> Dateninhalte (Pfeil ->) ${=FunktionsName(->Kunde->Name)} // bzw <lmb type="func" name="FunktionsName"><lmb type="data" src="->Kunde->Name" /></lmb> Funktionsaufruf (Gleichheitszeichen =) ${=FunktionsName(=AndererFunktionsName())} <lmb type="func" name="FunktionsName"><lmb type="func" name="AndererFunktionsName" /></lmb // Die innere Funktion kann dabei wieder die gleichen Typen von Parametern haben Das Ergebnis der Funktion sollte gültiges Html sein, das an der Stelle eingefügt wird. Gibt die Funktion stattdessen ein Objekt der Klasse TemplateElement (extra/template/base/TemplateElement.php) zurück, wird dieses an der Stelle eingebunden. If/Else/Endif ${if =FunktionsName()}...${endif} // bzw <lmb type="if"><lmb condition="func" name="FunktionsName" /></lmb> ... <lmb type="endif" /> ${if ->EinDatenFeld}...${endif} // bzw <lmb type="if"><lmb condition="data" src="EinDatenFeld" /></lmb>...<lmb type="endif" /> ${if =FunktionsName()}...${elseif ->EinDatenFeld}...${else}...${endif} // bzw <lmb type="if"><lmb condition="func" name="FunktionsName" /></lmb> ... <lmb type="elseif"><lmb condition="data" src="->EinDatenFeld" /></lmb> ... <lmb type="else" /> ... <lmb type="endif" /> Wertet die Funktion report_FunktionsName/form_FunktionsName bzw. das Feld EinDatenFeld aus. Evaluiert der Wert zu true, wird der Teil zwischen if und endif im Bericht ausgegeben, andernfalls nicht. Zwischen beiden werden auch ${elseif ...} und ${else} unterstützt. Beispiel Es wird ein Bericht für die Tabelle Kontakte erstellt. In das Berichts-Element im Editor wird folgender Text eingetragen: ${Rechnung} Dies bewirkt, dass in dem Bericht der Inhalt des Datensatzes mit Namen Rechnung aus der Berichtsvorlagen-Tabelle eingefügt wird. In diesem ist der Inhalt definiert: ${PersonenDaten} Rechnung Text Blabla In dem Datensatz mit Namen PersonenDaten: ${->Anrede} ${->Vorname} ${->Nachname}, geb. ${=formatDate(->GeburtsDatum,"d.m.Y")} Es werden hier Anrede/Vorname/Nachname aus der Tabelle Kontakte von dem Datensatz genommen, für den der Bericht gedruckt wird. An die Funktion wird als erster Parameter das Geburtsdatum des Kontakts übergeben (aus der Datenbank). Als zweiter Parameter wird direkt der String d.m.Y übergeben. So kann die Funktion für weitere Datumsformate wiederverwendet werden. Sie kann beispielsweise so in einer Erweiterung (ext_report.inc) implementiert sein: function report_formatDate($date, $format) { $stamp = strtotime($date); return date($format, $stamp); } So hat der Bericht eine klare Struktur, kann direkt mit Html designed werden und die Personendaten können in weiteren Berichten wiederverwendet werden. Tabellen Oft möchte man in Berichten nicht nur einen verknüpften Datensatz anzeigen, sondern eine Tabelle, in der alle aufgelistet werden. Mit der Kundenliste oder der Auflistung der Positionen in der Rechnung sind hierfür einige Beispiele in der Demo finden. Die Wiederholung wird pro Tabellen-Zeile definiert. So lassen sich in einer Tabelle auch mehrere Auflistungen hintereinander anzeigen. Auch muss festgelegt werden, über welche Verknüpfung iteriert werden soll. Mit dem Wysiwyg-Editor selektiert man ein Feld der gewünschten Zeile und definiert über den Menüeintrag Tabelle->Data row die Verknüpfung. Die Zeile wird jetzt oben und unten mit gestricheltem Rand dargestellt. Tabelle im Wysiwyg-Editor, zweite Zeile wird für alle Kontakte wiederholt Arbeitet man nicht mit dem Wysiwyg-Editor, kann die Wiederholung mit dem Attribut data-lmb-data-row definiert werden. Der Wert des Attributs ist dabei das Verknüpfungsfeld, in der Pfeil-Schreibweise (Siehe Dateninhalt). In dem folgenden Beispiel wird über alle Positionen des Datensatzes iteriert: <tr data-lmb-data-row="->Positionen">...</tr> Es kann auch über „entferntere“ Verknüpfungsfelder iteriert werden, z.B. über die Adressen des ersten verknüpften Kontakts: <tr data-lmb-data-row="->Kontakte->Adressen">...</tr> Es ist möglich, wiederholte Zeilen in einander zu verschachteln, also in einem Feld einer wiederholten Tabelle eine weitere Tabelle zu erstellen, in der wieder Zeilen wiederholt werden. Datenfelder in der wiederholten Zeile werden dann für jede Zeile korrekt aufgelöst. Möchte man in Listenformularen über die Basistabelle iterieren, kann folgende Syntax verwendet werden: <tr data-lmb-data-row="=>BasisTabellenName">...</tr> Filter Die Verknüpfung, über die iteriert wird, kann mit einer Erweiterung gefiltert werden. So können bspw. immer nur maximal 5 Datensätze angezeigt werden, oder nur alle Datensätze, die einen bestimmten Feld-Inhalt haben. Eine Filter-Funktion, definiert in einer Extension (siehe Skript-Erweiterungen), gibt ein Array mit den optionalen Einträgen gsr, filter und extension zurück. Diese entsprechen den Parametern der Funktion get_gresult: function report_filterTable() { $gsr = array(); $gsr[tableID]... $filter = array(); ... $extension = array(); ... return array('gsr' => $gsr, 'filter' => $filter, 'extension' => $extension); } Um eine Filter-Funktion einzutragen, setzt man im Wysiwyg-Editor den Cursor in die entsprechende Zeile und wählt über den Menüpunkt Tabelle -> Wdh. Zeile-Filter die Funktion aus. Im Html kann die Funktion alternativ über das Attribut data-lmb-data-row-filter gesetzt werden. Die Notation der Funktion ist dabei gleich wie beim Funktions-Platzhalter. Funktionsaufrufe Funktionsaufrufe werden normalerweise nur einmal ausgeführt, das Ergebnis wird in jeder Zeile erneut ausgegeben. Möchte man, dass eine Funktion für jede Zeile neu ausgeführt wird, muss einer ihrer Parameter ein Funktionsaufruf der Funktionen index oder tableRowData (s.u.) sein. Utility-Funktionen Limbas stellt eine Reihe von Funktionen zur Verfügung um in eigenen Erweiterungen sinnvoll die Daten der wiederholten Tabelle nutzen zu können. Zeilen-Index Die Funktion index($startFrom=0, $depth=0) gibt den Index der aktuellen Zeile an. Wird kein Parameter übergeben, ist der Index 0-basiert. Möchte man aber z.B. im Bericht in der ersten Spalte den Index ausgeben, sollte er bei 1 beginnen. Dafür kann der erste Parameter ($startFrom) auf 1 gesetzt werden. Sind mehrere wiederholte Tabellenzeilen in einander verschachtelt, kann mit dem zweiten Parameter ($depth) zwischen den Zeilen unterschieden werden. Standardmäßig ($depth=0) wird der Index der „nähesten“ Tabellenzeile zurückgegeben. Möchte man z.B. den Index einer äußeren Tabelle haben, kann $depth auf 1 gesetzt werden. Das Verhalten ist also so wie bei PHPs continue oder break Befehlen. Spalten-Index Die Funktion colIndex($startFrom=0, $depth=0) ist so wie index, nur dass der Index der Spalte zurückgegeben wird. Datensatz-ID Die Funktion datid($depth=0) gibt die ID des aktuellen Datensatzes zurück. Dieser ist auf jeden Fall durch den Datensatz definiert, für den das Formular/der Bericht gedruckt wird. In wiederholten Tabellenzeilen wird die Datensatz-ID des verknüpften Datensatzes zurückgegeben. Der Parameter $depth verhält sich genauso wie bei index. Die Basis-Datensatz-ID ist als „größte“ Tiefe gespeichert. Ist man gerade nicht in einer wiederholten Tabellenzeile, bekommt man diese also durch datid(0) oder einfach datid(). Wenn an in einer wiederholten Tabellenzeile ist, kriegt man sie mit datid(1). Daten der Tabelle Oft möchte man in/unter der Tabelle einen Wert anzeigen, der aus den bisherigen Einträgen der Tabelle berechnet wird, z.B. eine Summe der Preise in der Tabelle. Dafür kann die Funktion tableRowData() benutzt werden. Wird sie innerhalb einer wiederholten Zeile aufgerufen, enthält sie die Werte der Zeile bisher, also alle Zellen. Innerhalb der Zelle sind alle Elemente aufgelistet: $data[<Spalten-Index>][<Element-Index>]: mixed Wird die Funktion nach einer wiederholten Zeile aufgerufen, enthält sie Werte aller bisherigen wiederholten Zeilen. Diese sind unter der Pfeil-Syntax gespeichert: $data[<Verküpfungs-Pfeil-Syntax>][<Zeilen-Index>][<Spalten-Index>][<Element-Index>]: mixed So addiert man bspw. alle Werte, die in der Positionen-Auflistung in der 3. Spalte als 1. Element stehen: foreach ($data[->Positionen] as $row) { $sum += intval($row[2][0]); }