Arbeiten mit der Klasse Control

In TopLogic existieren abstrakte Klassen, von welcher geerbt werden kann, um eine Control Klasse zu programmieren. Die zu implementierenden und vorhandenen Methoden sind je nach abstrakter Klasse verschieden. Die Klasse, die zum erben häufig verwendet wird und die im Beispiel eingesetzt wird, ist AbstractFormFieldControl.

Der Konstruktor von ButtonDyerControl wird durch einen Erzeugung von Control-Instanzen aufgerufen. Das sich der Button verändert, wenn ein Anwendungsnutzer auf diesen klickt, wird mit JavaScript realisiert (Verbindung zwischen Client und Server). Damit der Klick wieder auf der Server-Seite bemerkt wird, braucht es ein Verbindungsglied, dass bei uns Kommandos sind. Darauf wird weiter Unten genauer eingegangen.

public class ButtonDyerControl extends AbstractFormFieldControl {

	protected static final Map<String, ControlCommand> COMMANDS = createCommandMap(
		AbstractFormFieldControlBase.COMMANDS,
		new ControlCommand[] { ChangeColorCommand.INSTANCE });

	private boolean isDark = true;

	protected ButtonDyerControl(FormField model) {
		super(model, COMMANDS);
	}

}

AbstractFormFieldControl besitzt 4 abstrakte Methoden, welche in unserem Kontroll implementiert werden müssen. writeEditable ist das Herzstück der Kontrollklasse. In dieser dürfen wir das Feld so zeichnen, wie wir wollen. Die einzigen Regeln, an die man sich halten muss, sind die HTML Regeln und die Top Logic Syntax. Das Thema wird genauer in Erstellen von HTML Elementen unter die Lupe genommen.

@Override
protected void writeEditable(DisplayContext context, TagWriter out) throws IOException {
	StringField buttonStringField = (StringField) getModel();
	out.beginBeginTag(HTMLConstants.SPAN);
	writeControlAttributes(out);
	out.endBeginTag();
	out.beginBeginTag(HTMLConstants.BUTTON);
	writeInputIdAttr(out);
	if (isDark) {
		out.writeAttribute(HTMLConstants.CLASS_ATTR, "darkButtonClass");
	} else {
		out.writeAttribute(HTMLConstants.CLASS_ATTR, "lightButtonClass");
	}
	if (buttonStringField.isDisabled()) {
		out.writeAttribute(DISABLED_ATTR, DISABLED_DISABLED_VALUE);
	}
	out.beginAttribute(HTMLConstants.ONCLICK_ATTR);
	writeJSAction(out, "services.form.ButtonDyerControl", "handleButtonClick", this, null);
	out.endAttribute();
	out.endBeginTag();
	out.writeText("Text");
	out.endTag(HTMLConstants.BUTTON);
	out.endTag(HTMLConstants.SPAN);
}

Die internalHandleValueChanged() Methode sollte requestRepaint() ausführen, was dafür sorgt, dass das Modell auf der Client Seite neu gezeichnet wird. Nach dem Aufrufen von requestRepaint() wird writeEditable() am Ende wieder ausgeführt.

@Override
protected void internalHandleValueChanged(FormField field, Object oldValue, Object newValue) {
	requestRepaint();
}

Wenn man möchte, kann man den Button deaktivieren. In Top Logic gibt es Funktionien, welche die Felder auf einer Seite der Anwendung ausschalten.

@Override
protected void internalHandleDisabledEvent(FormMember sender, Boolean oldValue, Boolean newValue) {
	addDisabledUpdate(newValue.booleanValue());
}

Nebst dem deaktivieren von Feldern, gibt es noch die Möglichkeit diese obligatorisch oder unveränderlich zu machen. Ein Button kann jedoch nicht obligatorisch sein, weshalb diese Funktion nicht berücksichtigt werden muss. Dennoch fügen wir ein Beispiel dazu unterhalb der writeImmutable() Methode ein.

@Override
protected void writeImmutable(DisplayContext context, TagWriter out) throws IOException {
	StringField buttonStringField = (StringField) getModel();
	out.beginBeginTag(SPAN);
	writeControlAttributes(out);
	out.endBeginTag();
	out.beginBeginTag(SPAN);
	out.writeAttribute(HTMLConstants.CLASS_ATTR, "changeColorImmutable");
	out.endBeginTag();
	out.writeText(buttonStringField.toString());
	out.endTag(SPAN);
	out.endTag(SPAN);
}

@Override
public Bubble handleMandatoryChanged(FormField sender, Boolean oldValue, Boolean newValue) {
	if (!skipEvent(sender)) {
		requestRepaint();
	}
	return Bubble.BUBBLE;
}

Bei der Implementierung von eigenen Control Klassen gibt es wichtiges zu beachten:

  • Man kann Verschachtlungen vornehmen, sodass beispielsweise ein span in einem anchor Tag liegt. Die Tags müssen genauso geschrieben werden, wie in den Beispielen Erstellen von HTML Elementen.
  • Das wichtigste ist, dass ein Element existiert, welches die Kontroll Attribute bekommt. In der HTML Baumstruktur sollte es das oberste Element sein. Das darf nicht vergessen werden, weil ein Control deutlich gekennzeichnet werden muss, da es für die Weiterverarbeitung benutzt wird. Mit dieser Methode werden dem Element Klassen hinzugefügt, mit der TopLogic Felder verändern und erkennen kann.
  • Die writeInputIdAttr() Methode übergibt dem Element eine ID und auch die darf nur einem Element zugewiesen werden. Oft wird es dem zweitobersten Element übergeben.
  • Während man in einem Tag am programmieren ist, welches ein Kontroll oder ID Attribut erhalten hat, darf es kein weiteres Element geben, welches die Control oder das ID Attribute bekommt. Das andere Element würden die gleiche ID erhalten und Funktionen wie z.B. writeImmutable() würden fehlerhaft ausgeführt werden.
  • Mit der Methode getID() erhält man die einzigartige ID des Feldes.

Wenn man die writeControl Methode nutzt, werden dem Element bereits Klassen hinzugefügt. Was wenn man dem span Element eine eigene Klasse hinzufügen möchte? Der Versuch, out.writeAttribute(HTMLConstants.CLASS_ATTR, "test"); nach der writeControl Methode zu benutzen, wird eine Fehlermeldung zurückgeben, weil das Programm dem Element zweimal class="" Attribute hinzufügen möchte und das ist in HTML/CSS nicht möglich. Der Trick, um eine zusätzliche Klasse neben den Kontroll Klassen hinzuzufügen, ist , die folgende Methode zu implementieren:

@Override
protected String getTypeCssClass() {
	return "test";
}

Damit der Button auch das gewünschte Design hat, muss der template.css Datei die CSS Regeln mitgegeben werden. ​

.darkButtonClass {
	background-color: darkgrey;
	color: white;
}

.lightButtonClass {
	background-color: white;
	color: red;
}