Rendering

Beispiel

Mit dem Rendering kann man sich das lästige Markupschreiben sparen und einfach per YAML konfigurieren.

Hier nochmal die Rendering-Konfiguration aus Beispiel 1 (einfaches Formular):

renderer:                                                          # hier werden die Renderer des Formulars definiert
  default:                                                         # Der Standard-Renderer hat den Namen default
    _type: form                                                    # das Root-Widget ist vom Typ form
    id: 'contact'                                                  # DOM-ID des <form>
    fields:                                                        # fields gibt die Kinder-Widgets an
      _info:     { _type: form_message, wrap: {div: status } }     # Das form_message-Widget gibt die Formularmeldung aus. Über den wrap-Parameter wird es mit einem <div class="status"> umschlossen.
      name:      { _type: text,      label: 'Name:' }              # <input> und <label> für name
      email:     { _type: text,      label: 'E-Mail:' }            # <input> und <label> für email
      message:   { _type: textarea,  label: 'Nachricht:' }         # <textarea> und <label> für message
      _submit:   { _type: submit,    value: 'Senden' }             # submit-Button

durch

<?php echo WV30_Form::getForm('contact', true)->render() ?>

wird folgendes Markup wird vom Renderer generiert (und auch das Form verarbeitet).

<form method="post" action="kontakt/" id="contact">
  <div style="display:none"><input type="hidden" value="contact" name="__wv30_form_id"></div>
  <div class="status"></div>
  <label for="default_name">Name:</label>
  <input type="text" value="" name="name" id="default_name">
  <label for="default_email">E-Mail:</label>
  <input type="text" value="" name="email" id="default_email">
  <label for="default_message">Nachricht:</label>
  <textarea name="message" rows="3" cols="25" id="default_message"></textarea>
  <input type="submit" value="Senden" id="default__submit">
</form>

Natürlich bekommen die Elemente ggf. Error-Klassen und geben die Nutzereingaben wieder aus, falls beim Abschicken Fehler auftraten.

Das Beispiel Schritt für Schritt

Ein Formular kann mehrere Renderer haben. Hat es nur einen, sollte man diesen “default” nennen.

Unter default wird das Root-Widget des Renderers definiert. _type gibt den Typ des Widgets an. Abhängig davon wird die entsprechende Widgetklasse instanziiert.

Im Beispiel WV30_Widget_Form weil Typ gleich form ist. Das WV30_Widget_Form sorgt für das <form>-Tag. Es bekommt auch die zugewiesene id. Die id ist gleichzeitig Prefix für die untergeordneten Widgets. Außerdem rendert es das versteckte Feld mit dem Formular-Key.

WV30_Widget_Form und andere Eltern-Widgets haben den Parameter fields. In einem assoziativen Array können hier untergeordnete Widgets definiert werden. Die Keys des Arrays können sich - müssen aber nicht - auf Formular-Felder beziehen. Beziehen sich die Keys nicht auf Formular-Felder haben die zugeordneten Widgets nur einen strukturellen oder informativen Nutzen. Im Beispiel beginnen diese Keys mit einem Unterstrich (_info, _submit). Die Werte des assoziativen Arrays sind Widgetdefinitionen genau wie beim Root-Widget. Verpflichten ist hier zumindest der _type-Parameter der widget die Widgetklasse festlegt.

  • _info Das Widget “form_message” gibt die Formularfehlermeldung aus.
  • name Das Widget “text” gibt für das Formularfeld “name” das Input aus.
  • _submit Das Widget “submit” gibt einen Submit-Button aus.

Es existieren eine Reihe allgemeiner Parameter, die alle Widgets akzeptieren. Die wichtigsten sind wrap, label, class und label_after. Genauer sind diese weiter unten bei “Parameter aller Widgets” beschrieben.

Hinter den Kulissen

Das Rendering des Formulars geschieht über Widgets. Dies sind Klassen, die von WV30_Widget abgeleitet sind.

Die Klasse WV30_Widget stellt eine Reihe wichtiger Basisfunktionalitäten bereit, die eigentlich jedes Widget benötigt. Alle Widgets lassen sich über Parameter konfigurieren. Damit man die Übersicht über alle Parameter behält werden alle möglichen Parameter als Konstanten der Klasse definiert (siehe Quellen von WV30_Widget).

Eltern-Widgets

Ein sehr wichtiger Paramter der Klasse WV30_Widget ist fields. Über fields kann man eine Liste von Kinder-Widgets angeben, die das Widget rendern soll. Die Kinder-Widgets können möglicher Weise wieder Kinder-Widgets haben usw. Dadurch ergibt sich ein Widget-Baum. Alle Widgets, die Kinder-Widgets rendern sollen, müssen direkt von WV30_Widget oder von Klassen, die die Methode doRender() nicht überschrieben haben, abgeleitet werden. Ein Beispiel dafür ist WV30_Widget_Form (form).

Ein fields-Eintrag hat als Key den Formularfeld-Namen und als Value die Parameter des Widgets. Dabei muss einer der beiden speziellen Paramter _type oder _class angegeben sein, damit das Eltern-Widget die Klasse des Widgets herausfinden kann: _class ist direkt der Klassenname - _type der Name des Widgets wie er in der static.yml oder in der _static-Sektion der Konfiguration definiert ist.

Bezieht sich ein fields-Eintrag nicht direkt auf ein Formularfeld, so kann als Key einfach ein beliebiger anderer freie Namen verwendet werden. Zur Übersichtlichkeit haben diese im Beispiel einen Unterstrich als Prefix (_info, _submit).

einfache Widgets

Die meisten Widgets überschreiben die Methode doRender() und liefern das gewünschte Markup zurück. Zum Rendern des Widgets wird aber nicht direkt die doRender() aufgerufen, sondern die render()-Methode. Dies sorgt dafür, dass Goodies wie die Parameter wrap, wrap_inner, label, label_after, item_class usw. funktionieren. Zur Entwicklung eigener Widgets sei vorerst auf die Quellen verwiesen. Die vorhandenen Widgets sind leicht verständlich und sollten als Grundlage für Widget ausreichend sein.

mehrere Renderer für das gleiche Formular

Hat man alternative Ansichten für das gleiche Formular, nimmt man nicht den Namen default, sondern weitere Namen und ruft den entsprechenden Renderer so auf:

<?php echo WV30_Form::getForm('contact', true)->render('alternative1') ?>

Widgets

Parameter aller Widgets

fields
(nur für Eltern-Widgets) Liste der Kinder-Wigdet (siehe oben)
id
DOM-ID des Widgets fest setzen, wird dann nicht automatisch erzeugt
label
Label vor dem Widget
label_after
Label nach dem Widget
label_wrap
Label umschließt das Widget (spart das for-Attribut)
class
CSS-Klasse
wrap

Widget mit DOM-Element wrappen

  • wrap: div -> <div>...</div>
  • wrap: {div: foobar} -> <div class="foobar">...</div>
wrap_inner
wie wrap, nur das die Label (label, label_after) nicht eingeschlossen werden.
wrap_item
(nur für Eltern-Widgets) alle Kinder-Widgets mit DOM-Element wrappen
item_class
(nur für Kinder-Widgets) falls das Eltern-Widget @wrap_item@ benutzt, kann dem DOM-Element eine CSS-Klasse hinzugefügt werden
repeat
(nur für Eltern-Widgets) Doku kommt noch
repeat_max
(nur für Eltern-Widgets) Doku kommt noch
default_value
vorbelegter Wert des Formular-Elementes
default_value_callback
vorbelegten Wert mit Callback holen (z.B. default_value_callback: [MyClass, getDefault])
default_value_callback_param
Paramter für Callback

Liste der Widgets

list: WV30_Widget_List
einfaches Eltern-Widget. Will man z.B. eine Gruppe von Widget in einen <div>-Container legen, so legt man diese in ein list-Widget und nutzt den Paramter wrap
form: WV30_Widget_Form
Eltern-Widget, rendert <form>-Tag und fügt hidden-field mit Formularkey hinzu.
input: WV30_Widget_Input
Basis-Widget für die meisten <input>-Widgets
text: WV30_Widget_Text
Text-Input
textarea: WV30_Widget_Textarea
Textarea
submit: WV30_Widget_Submit
Submit-Button
form_message: WV30_Widget_FormMessage
Formular-Meldung
hidden: WV30_Widget_Hidden
verstecktes Feld
template: WV30_Widget_Template
rendert beliebiges Template über TemplateService (siehe Quellen)
plaintext: WV30_Widget_PlainText
rendert festen Text (Paramter: text)
link: WV30_Widget_Link
rendert <a>-Link mit fester URL oder aus Global-Setting (Paramter: text, href, global_setting)
callback: WV30_Widget_Callback
führt PHP-Callback aus (Paramter: callback, params)
select: WV30_Widget_Select
rendert Select (siehe Quellen, hat auch Callback)
radio: WV30_Widget_RadioButton
rendert RadioButtons (siehe Quellen, hat auch Callback)
checkbox: WV30_Widget_Checkbox
rendert Checkbox (siehe Quellen, hat auch Callback)
file: WV30_Widget_File
rendert FileUpload
honeypots: WV30_Widget_Honeypots
rendert versteckte Honeypot-Felder (ohne Konfiguration, einfach reinpacken und gut)

Beispiel 2

Hier ein etwas komplexes aber noch relativ einfaches Beispiel:

kontakt:
  name: Kontakt
  fields: [name, firma, email, telefon, zeiten, nachricht]
  required: [name, email, nachricht]
  validators:
    email: mail
  processors:
    mail:
      type: mail
  renderer:
    default:
      _type: form
      id: 'form_kontakt'
      wrap: {div: form}
      fields:
        _head: { _type: plaintext, text: 'Schreiben Sie uns!', wrap: h4}
        _info: { _type: form_message, wrap: {div: status } }
        _main:
          _type: list
          wrap_item: {div: widget }
          fields:
            name:      { _type: text,     label: 'Name*:' }
            firma:     { _type: text,     label: 'Firma:' }
            email:     { _type: text,     label: 'E-Mail-Adresse*:' }
            telefon:   { _type: text,     label: 'Telefon:' }
            zeiten:    { _type: text,     label: 'Gewünschte Rückrufzeiten:' }
            nachricht: { _type: textarea, label: 'Nachricht*:' }
            honeypots: { _type: honeypots, wrap: {div: pot} }
        _footer:
          _type: list
          wrap: {div: footer}
          fields:
            _note: {_type: plaintext, text: '* Pflichtangaben', wrap: span }
            _submit: { _type: submit, value: 'Senden', wrap: {div: submit}, label: ' ', label_after: ' ' }

Inhalt

Vorheriges Thema

Prozessoren

Nächstes Thema

Rendering-Module

Diese Seite