Logo Oracle Deutschland   Application Express Community
APEX-Formulare gestalten - eigene Layouts mit CSS
Erscheinungsmonat APEX-Version Datenbankversion
Oktober 2011 APEX 4.1 10.2

Nachdem sich der letzte Tipp mit der Formatierung eines klassischen Berichts mit Hilfe von Report-Templates beschäftigte, widmen wir uns heute einem verwandten Thema: Lesen Sie heute, wie Sie das Layout eines APEX-Formulars mit Hilfe von CSS-Angaben (CSS = Cascading Style Sheets) beeinflussen können. Der Tipp hat jedoch nicht den Anspruch, CSS vollständig zu erklären oder eine umfassende Referenz abzuliefern - hierfür gibt es bereits zahlreiche Webseiten und Literatur - eine sehr gute deutschsprachige Webseite zum Thema ist SelfHTML - der Bereich CSS enthält sehr ausführliche, grundliegende Informationen zum Thema.

Einige der hier vorgestellten Layout-Effekte wie abgerundete Ecken und Schatte für Eingabefelder funktionieren nur im Firefox und in Webkit-basierenden Browsern wie Google Chrome oder Safari einwandfrei.

Das Layout für Eingabefelder anpassen

Beginnen wir mit dem Formatieren eines Texteingabefeldes. Abbildung 1 zeigt ein APEX-Formular, welches mit dem Assistenten auf die Tabelle EMP "normal" angelegt wurde.

Ein APEX-Formular direkt nach Erstellung

Abbildung 1: Ein APEX-Formular direkt nach Erstellung

Beginnen wir damit, das Eingabefeld zu formatieren. Navigieren Sie dazu zum Element P2_ENAME , dort zum Abschnitt Element und tragen Sie bei HTML-Form-Elementattribute folgenden HTML-Code ein: style="background-color: yellow; font-weight: bold;" (Abbildung 2).

Das APEX-Element wird mit CSS-Angaben direkt formatiert

Abbildung 2: Das APEX-Element wird mit CSS-Angaben direkt formatiert

Das HTML-Attribut style können Sie in jedem HTML-Tag verwenden - dort durch Semikolon getrennte CSS-Angaben hineingeschreiben, mit denen das HTML-Element dann vom Browser formatiert wird. Generell sollten Sie für alle Arten der Formatierung nach Möglichkeit CSS-Angaben verwenden - "alte" HTML-Tags wie <b> , <font> und ähnliche sollten allenfalls in Ausnahmefällen verwendet werden. Schauen Sie sich das Ergebnis zunächst einmal an (Abbildung 3).

Das formatierte APEX-Formularelement

Abbildung 3: Das formatierte APEX-Formularelement

Nicht unbedingt schön, aber selten ... könnte man sagen. Vor der Verbesserung oder Verfeinerung dieser Formatierungen wollen wir jedoch noch andere Möglichkeiten kennenlernen, einem HTML-Tag eine CSS-Formatierung zuzuweisen: Denn die hier vorgestellte Variante mit dem Attribut style hat natürlich massive Nachteile. Angenommen, wir wollten alle Formularelemente gleich formatieren, so müssten wir das Attribut überall kopieren; und wenn man die Formatierung ändern möchte, muss man auch die Änderung überall konsistent durchführen - das Attribut style ist also nur für einmalige Formatierungen bzw. für Abweichungen vom Layout-Standard geeignet.

Sobald man CSS-Formatierungen mehr als einmal anwenden möchte, bieten sich CSS-Klassen an. Dazu navigieren Sie zum Seitentemplate Ihrer APEX-Seite und klicken im Kontextmenü auf Bearbeiten (Abbildung 4).

Seitentemplate bearbeiten

Abbildung 4: Seitentemplate bearbeiten

Schaffen Sie sich im Bereich Header ein wenig Platz, indem Sie ein paar Leerzeilen einfügen und tragen Sie dort, wie in Abbildung 5 dargestellt, die HTML-Tags <style> und </style> ein. Dazwischen werden wir im folgenden die CSS-Klassen definieren.

CSS-Definitionen können innerhalb des HTML-Tags <style> gemacht werden

Abbildung 5: CSS-Definitionen können innerhalb des HTML-Tags <style> gemacht werden

Definieren Sie nun eine CSS-Klasse numfeld für numerische Felder und eine für Textfelder (textfeld). Dazu kommt eine generelle Formatanweisung für alle <input> und <select>-Tags (<input> ist das HTML-Tag, welches für alle Texteingabefelder verwendet wird; <select> erzeugt eine Auswahlliste).

/* Textfelder werden mit blauer Schrift auf grauem Hintergrund dargestellt.
 */
.textfeld {
  color: blue;
  background-color: #cccccc;
}

/* Numerische Felder erhalten grüne Schrift auf weißen Hintergrund.
 */
.numfeld {
  color: green;
  background-color: white;
}

/* Alle Eingabefelder erhalten ...
 * - einen drei Pixel breiten inneren Rand
 * - fette, 16 Punkt große Schrift
 * - einen 1 Pixel dünnen grauen Rahmen
 * - Auf Firefox, Safari und Chrome: einen abgerundeten Rand
 */
select,input {
  padding: 3px;
  font-weight: bold;
  font-family: Arial, Sans-Serif;
  font-size: 16pt;
  border-radius: 5px;
  -moz-border-radius: 5px;
  -webkit-border-radius: 5px;
  border: 1px solid gray;
}

Wenn Sie die Seite nun nochmal starten, sehen Sie, dass die Formatangeben, die Sie für <input> und <select> festgelegt haben, sofort wirksam sind; die beiden Klassen für numerische und Textfelder dagegen noch nicht. Und das ist logisch, denn der Browser weiss ja noch gar nicht, welche Felder Sie als numerisch und welche Sie als Textfeld ansehen möchten. Das wird nun festgelegt. Navigieren Sie zu den einzelnen Eingabefeldern, wie vorhin in den Bereich Element und dort zu HTML-Form-Elementattribute. Bei den Textfeldern setzen Sie dort class="textfeld" und bei den numerischen Feldern setzen Sie class="numfeld" ein (Für HIREDATE nehmen Sie eines der beiden). Wenn Sie eine Auswahlliste, Checkboxes oder eine Radiogroup haben, tragen Sie die Anweisung auch bei Form-Element-Optionsattribute ein. Starten Sie die Seite danach neu - sie sollte nun wie in Abbildung 6 aussehen.

Die neu formatierte Formularseite

Abbildung 6: Die neu formatierte Formularseite

Besonders interessant ist die CSS-Anweisung border-radius und deren Präfixe für ältere Firefox- (-moz-) und Safari-Browser (-webkit): diese können Sie nahezu überall verwenden und sie sorgt für abgerundete Ecken - leider interpretiert der Microsoft Internet Explorer sie erst ab Version 9. Das gleiche gilt für das im Folgenden verwendete box-shadow.

Fügen Sie dann eine CSS-Klasse namens aktfeld, für das Feld hinzu, auf dem sich der Cursor gerade befindet - denn dieses soll nun besonders hervorgehoben werden. Fügen Sie diese Anweisungen zu den anderen CSS-Angaben innerhalb der <style>-Tags im Seitentemplate ein.

/* Textfelder werden mit blauer Schrift auf grauem Hintergrund dargestellt.
 */
.aktfeld {
  color: red;
  background-color: yellow;
  box-shadow: #666 8px 8px;
  -moz-box-shadow: 5px 5px 5px #666;
  -webkit-box-shadow: 5px 5px 5px #666;
}

Zunächst passiert natürlich noch nichts - denn die CSS-Klasse aktfeld muss dem Eingabefeld nun beim Aktivieren zugewiesen werden. Beim Verlassen des Feldes muss dagegen die alte CSS-Klasse wiederhergestellt werden. Das können Sie erreichen, in dem Sie zu den Attributen für jedes Eingabefeld navigieren. Dort gehen Sie, wie vorhin, zum Bereich Element und dort wiederum zu HTML-Form-Elementattribute. Dort tragen Sie für jedes Feld ein:

onFocus="$(this).attr("class", "aktfeld");" onBlur="$(this).attr("class", "{textfeld oder numfeld}");"

Eleganter geht es ab APEX 4.0 mit ein wenig JavaScript und jQuery. Navigieren Sie zu den Seitenattributen und dort zu Beim Laden der Seite ausführen - hinterlegen Sie hier folgenden JavaScript-Code.

jQuery.each($('[id^=P2_]'), function()  {
  var e = $(this).attr("class");
  $(this).blur(function () {
    $(this).attr('class', e);
  });
  $(this).focus(function () {
    $(this).attr('class', 'aktfeld');
  });
});

Dieser Code fügt jedem Formularelement einen Event-Handler für onFocus (wenn das Feld betreten wird) und für onBlur (wenn das Feld verlassen wird) hinzu. Beim Betreten wird die CSS-Klasse aktfeld gesetzt, beim Verlassen wird die alte Klasse wiederhergestellt. Für Radiobuttons und Checkboxes wird das noch nicht ganz wie gewünscht aussehen, das wird aber zum Ende dieses Tipps hin korrigiert.

Element-Labels in die Elemente selbst setzen

Als nächstes geht es an die Darstellung der Labels - nahezu alle Web-Anwendungen sehen so aus, dass das Label entweder links vom oder über dem Eingabefeld steht. Gerade wenn es aber darum geht, Platz auf der Seite zu sparen, wäre es eine interessante Alternative, das Label im Eingabefeld selbst zu platzieren und auszublenden, sobald das erste Zeichen eingegeben wurde (Abbildung 7). In Frage kommt das vor allem dort, wo die Formularinhalte selbsterklärend sind und man die Labels eigentlich nur bei einem leeren Formular braucht.

Formularbeschriftungen in das Eingabefeld selbst setzen

Abbildung 7: Formularbeschriftungen in das Eingabefeld selbst setzen

Hierfür machen wir uns ein neues Feature in APEX 4.1 zunutze. Bis APEX 4.0 stellt APEX alle Formulare zwingend als HTML-Tabelle dar - wobei Label und Eingabefeld in unterschiedliche Tabellenzellen gepackt werden. Das macht es natürlich schwierig, das Label genau ins Eingabefeld selbst zu platzieren (denn Label und Eingabefeld sind unterschiedliche Tabellenzellen). In APEX 4.1 kann dieses Verhalten aber abgestellt werden. Navigieren Sie dazu zu den Templates, und kopieren Sie sich das Regions-Template, welches die Formularregion verwendet (Abbildung 8).

Regionstemplate für die Formularregion kopieren I
Regionstemplate für die Formularregion kopieren II
Regionstemplate für die Formularregion kopieren III
Regionstemplate für die Formularregion kopieren IV

Abbildung 8: Regionstemplate für die Formularregion kopieren und der Region zuweisen

Navigieren Sie dann zu der erstellten Kopie, geben Sie Ihr einen neuen Namen Forms Region ohne HTML Tabelle und stellen Sie die Auswahlliste Form-Elemente in Tabelle von Ja auf Nein (vergessen Sie nicht, der Formularregion Region das neue Template auch zuzuweisen).

HTML-Tabellendarstellung für Formularregionen ausschalten

Abbildung 9: HTML-Tabellendarstellung für Formularregionen ausschalten

Das bedeutet aber auch, dass alle Elementeinstellungen, die mit der Tabellendarstellung zu tun haben ( Neue Zeile, neues Feld , etc.) nun wirkungslos sind. Die Darstellung des Elements wird allein vom Label Template gesteuert. Und genau das werden wir nun, passend zur Anforderung, erstellen. Kopieren Sie sich das Label-Template Optional analog zur Vorgehensweise mit dem Region Template. Nennen Sie die Kopie Label im Feld und navigieren Sie zur Template-Bearbeitung (Abbildung 10).

Ein Label-Template bearbeiten

Abbildung 10: Ein Label-Template bearbeiten

Tragen Sie in die einzelnen Abschnitte folgende HTML-Fragmente ein:

  • For Label: <label for="#CURRENT_ITEM_NAME#" class="over">[
  • Nach Label: ]</label>
  • Vor Beschriftung und Element: <div class="label">
  • Nach Beschriftung und Element: </div>

Speichern Sie Ihr neues Label Template dann ab und weisen Sie es jedem Formularelement zu (Abbildung 11). Bei der Gelegenheit können Sie gleich passende Labels vergeben.

Das neue Label Template wird zugewiesen

Abbildung 11: Das neue Label Template wird zugewiesen

Das Zwischenergebnis sieht dann wie in Abbildung 12 aus.

Ein Zwischenergebnis

Abbildung 12: Ein Zwischenergebnis

Jetzt fehlen nur noch die CSS-Klassen label und over, die im Label-Template verwendet wurden und dafür sorgen, dass die Labels über das Eingebefeld selbst gelegt werden. Gehen Sie nochmals zum Seitentemplate und ergänzen Sie die Angaben innerhalb der Tags <style> und </style> um folgende CSS-Direktiven.

div.label {
    clear: left;
    float: left;
    margin-right: 0;
    margin-top: 10px;
    position: relative;
    font-family: Arial Narrow, Arial, Sans Serif;
    font-size: 14pt;
    font-weight: bold;
}

label.over {
    color: #dddddd;
    left: 5px;
    position: absolute;
    top: 6px;
}

Starten Sie die Seite nun nochmals - sie sollte nun wie in Abbildung 13 aussehen. Man sieht, dass die Labels sich nun schon, wie gewünscht, innerhalb der Eingabefelder befinden. Sobald man allerdings etwas tippt, bemerkt man, dass wir noch nicht ganz fertig sind.

Die Labels sind dort, wo sie sein sollen ...

Abbildung 13: Die Labels sind dort, wo sie sein sollen ...

Wenn man etwas in das Feld eintippt, sollen die Labels verschwinden. Das wird wiederum mit JavaScript erledigt. Bereits vorhin haben wir die Event-Handler onFocus and onBlur verwendet, um das jeweils aktuelle Eingabefeld hervorzuheben. Nun verwenden wir diese sowie die Handler onKeyDown und onKeyUp, um das Label ein- und auszublenden. Und das soll wie folgt geschehen:

  • Wenn ein Feld betreten wird, soll es hervorgehoben werden - das ist bereits erledigt
  • Das Label soll eingeblendet werden, wenn das Feld leer ist - sobald das erste Zeichen eingetippt wurde, wird es ausgeblendet. Hierfür benötigen wir die Handler onKeyDown und onKeyUp.
  • Wenn das Feld verlassen wird und leer ist, wird das Label eingeblendet - wenn es nicht leer ist, bleibt es ausgeblendet.
  • Für Auswahllisten, Checkboxes und Radiobuttons sollen die Labels generell ausgeblendet bleiben.

Der JavaScript-Code sieht wie folgt aus (hierin ist auch die "Sonderbehandlung" für Auswahllisten, Checkboxen und Radiogroups enthalten).

/*
 * jQuery.each: Gehe durch alle HTML-Elemente, deren ID mit "P2_" anfängt;
 *              das sind APEX-Elemente
 */
jQuery.each($("[id^=P2]:not([type=checkbox],[type=radio])").filter("input,select"), function()  {
  // Wenn etwas im Feld steht (aus der Tabelle), dann blende das Label aus 
  if ($(this).val().length > 0) {
    $("label.over[for='"+$(this).attr("id")+"']").hide();
  }
  // Sichere die CSS-Klasse
  var e = $(this).attr("class");

  // Füge einen Event-Handler onBlur() hinzu -> Beim Verlassen des Feldes
  $(this).blur(function () {
    // Weise die gesicherte CSS-Klasse wieder zu
    $(this).attr('class', e);
    // Wenn der Inhalt des Feldes leer ist (length == 0), blende das Label ein
    if ($(this).val().length == 0) {
      $("label.over[for='"+$(this).attr("id")+"']").show()
    }
  });

  // Füge einen Event-Handler onFocus() hinzu -> Beim Betreten des Feldes
  $(this).focus(function () {
    // Weise die CSS-Klasse "aktfeld" zu: Das Feld wird hervorgehoben
    $(this).attr('class', 'aktfeld');
  });

  // Füge einen Event-Handler onKeyDown() hinzu -> Wenn eine Taste gedrückt wurde
  $(this).keydown(function () {
    // Blende das Label aus ...
    $("label.over[for='"+$(this).attr("id")+"']").hide()
  });

  // Füge einen Event-Handler onKeyUp() hinzu -> Wenn die Taste losgelassen wurde
  $(this).keyup(function () {
    if ($(this).val().length == 0) {
      // Ist das Feld leer, blende das Label ein ...
      $("label.over[for='"+$(this).attr("id")+"']").show()
    }
  });
});

// Für Checkboxen und Radiogroups wird das Label *immer* ausgeblendet
jQuery.each($("select,fieldset"), function()  {
  $("label.over[for="+$(this).attr("id")+"]").hide();
});

Ersetzen Sie den JavaScript-Code in den Seitenattribute bei Beim Laden der Seite ausführen und starten Sie die Seite neu. Die Seite sollte nun aussehen, wie in Abbildung 14 dargestellt - und die Labels sollten reagieren, wie beschrieben.

Das Ergebnis: Das neue APEX-Formular

Abbildung 14: Das Ergebnis: Das neue APEX-Formular

Damit haben Sie Ihr Formular formatiert - Sie können das Eingabefeld für DEPTNO auch in eine Auswahlliste, eine Radiogroup oder Checkboxes umwandeln - CSS-Angaben und JavaScript-Code nehmen entsprechend Rücksicht auf deren Besonderheiten. Man sieht, dass sich APEX-Formulare durchaus anders darstellen lassen, moderne Layouts sind kein Problem.

Zurück zur Community-Seite