Dokumentation
List
Benötigt: Symcon >= 4.2
Erstellt eine Liste mit der Überschrift caption.
Die angezeigten Spalten werden in columns definiert.
Initiale Einträge der Liste können via values vorgegeben werden.

Allgemeine Parameter
| Parameter | Beschreibung |
|---|---|
| add (optional) | (default: false) Wenn true, dann wird unter der Tabelle ein "Hinzufügen"-Button eingeblendet, welcher der Tabelle ein neues Element mit Standardwerten hinzufügt |
| caption (optional) | Sichtbare Beschriftung der Liste |
| columns | Spalten der Liste |
| delete (optional) | (default: false) Wenn true, dann wird hinter jedem Eintrag in der Liste ein Button eingeblendet, welcher das entsprechende Element löscht |
| download (optional) | (default: "") Ist dieser Parameter nicht leer und beinhaltet die Ausgabe des onAdd, onChangeOrder, onDelete, onEdit oder onSelectionChanged-Skriptes eine Data-URL, so wird die Rückgabe als Textdatei mit dem Namen das download-Parameters heruntergeladen. (ab Symcon 7.0) |
| form (optional) | (default: basierend auf den edit-Parametern von columns) Ein individuelles Formular für den Dialog zum Hinzufügen und Bearbeiten von Zeilen. Die Definition erfolgt analog zur Definition des Formulars für Aktionen statisch als Array von Konfigurationselementen oder als PHP-Code, welcher für jede Zeile ein eigenes Formular erzeugen kann. Anwendungsfälle, Ablauf und Beispiele sind im Abschnitt Individuelle Formulare zum Bearbeiten beschrieben (ab Symcon 7.0) |
| link (optional) | (default: false) Ist dieser Parameter true, dann wird die Ausgabe des onAdd, onChangeOrder, onDelete, onEdit oder onSelectionChanged-Skriptes als Link geöffnet. Ist er false, so wird die Ausgabe als Dialog im Konfigurationsformular angezeigt. (ab Symcon 6.0) |
| multiAdd (optional) | (default: true, falls onAdd und form nicht gesetzt sind und nur eine einzige editierbare Spalte mit einer Objektauswahl existiert, sonst false) Als Objektauswahl gelten die Typen SelectObject, SelectCategory, SelectEvent, SelectInstance, SelectLink, SelectMedia, SelectScript oder SelectVariable. Ist dieser Parameter true, so wird beim Hinzufügen direkt die Objektauswahl der ersten sichtbaren Spalte mit einer Objektauswahl geöffnet, in der mehrere Objekte gleichzeitig ausgewählt werden können. Für jedes gewählte Objekt wird ein Eintrag hinzugefügt, dessen weitere Werte ihren add-Wert erhalten und anschließend über den Dialog bearbeitet werden können, siehe Mehrere Objekte hinzufügen. Beim Hinzufügen mehrerer Objekte wird onAdd trotzdem nur ein mal ausgeführt. Ist dieser Parameter false, so wird beim Hinzufügen der Dialog geöffnet. Existiert jedoch nur eine einzige editierbare Spalte mit einer Objektauswahl und ist form nicht gesetzt, so wird stattdessen direkt die Objektauswahl für ein einzelnes Objekt geöffnet. (ab Symcon 9.1) |
| name (optional) | Name der Liste / der zu setzenden Eigenschaft |
| onAdd (optional) | (default: "") Skript, welches nach dem Hinzufügen eines Eintrages der Liste ausgeführt wird. Sofern das Skript aus mehreren Zeilen besteht, können die einzelnen Zeilen auch als Array übergeben werden (Arrays werden ab Version 6.0 unterstützt). In dieser Ausführung bietet die Liste als Variablenwert nicht den aktuell ausgewählten Eintrag sondern den hinzugefügten Eintrag, siehe Ausgewählte Zeile als Variable in on-Aktionen. Ansonsten hat es die gleichen Eigenschaften wie onClick des Button (ab Symcon 5.3) |
| onChangeOrder (optional) | (default: "") Skript, welches nach dem Verschieben eines Eintrages der Liste ausgeführt wird. Sofern das Skript aus mehreren Zeilen besteht, können die einzelnen Zeilen auch als Array übergeben werden. In dieser Ausführung bietet die Liste als Variablenwert nicht den aktuell ausgewählten Eintrag sondern den verschobenen Eintrag, siehe Ausgewählte Zeile als Variable in on-Aktionen. Ansonsten hat es die gleichen Eigenschaften wie onClick des Button (ab Symcon 6.3) |
| onDelete (optional) | (default: "") Skript, welches nach dem Löschen eines Eintrages der Liste ausgeführt wird. Sofern das Skript aus mehreren Zeilen besteht, können die einzelnen Zeilen auch als Array übergeben werden (Arrays werden ab Version 6.0 unterstützt). In dieser Ausführung bietet die Liste als Variablenwert nicht den aktuell ausgewählten Eintrag sondern den gelöschten Eintrag, siehe Ausgewählte Zeile als Variable in on-Aktionen. Ansonsten hat es die gleichen Eigenschaften wie onClick des Button (ab Symcon 5.3) |
| onEdit (optional) | (default: "") Skript, welches nach der Bearbeitung eines Eintrages der Liste ausgeführt wird. Sofern das Skript aus mehreren Zeilen besteht, können die einzelnen Zeilen auch als Array übergeben werden (Arrays werden ab Version 6.0 unterstützt). In dieser Ausführung bietet die Liste als Variablenwert nicht den aktuell ausgewählten Eintrag sondern den bearbeiteten Eintrag, siehe Ausgewählte Zeile als Variable in on-Aktionen. Ansonsten hat es die gleichen Eigenschaften wie onClick des Button (ab Symcon 5.3) |
| onSelectionChanged (optional) | (default: "") Skript, welches ausgeführt wird, nachdem der Benutzer per Klick oder Pfeiltaste eine andere Zeile ausgewählt hat. Sofern das Skript aus mehreren Zeilen besteht, können die einzelnen Zeilen auch als Array übergeben werden. Die Liste bietet als Variablenwert die neu ausgewählte Zeile. Beim Aufheben der Auswahl und bei einer Änderung der Werte per UpdateFormField wird das Skript nicht ausgeführt, siehe Auf die Auswahl reagieren. Ansonsten hat es die gleichen Eigenschaften wie onClick des Button (ab Symcon 9.1) |
| rowCount (optional) | (default: 0) sichtbare Anzahl von Zeilen; bei mehr Zeilen in der Liste wird ein Scrollbalken eingeblendet - ist der Wert 0, so füllt die Liste den restlichen noch verfügbaren Platz im Instanzeditor. Nur ein Konfigurationselement kann den gesamten restlichen Platz erhalten. |
| sort (optional) | Sortierung der Tabelle. Wird dies nicht gesetzt bleibt die Liste unsortiert |
| type | List |
| values (optional) | Initiale Einträge der Liste |
| visible (optional) | (default: true) Bei true ist die Liste sichtbar, ansonsten ist sie unsichtbar (ab Symcon 5.2) |
| enabled (optional) | (default: true) Bei true kann die Liste verwendet werden, ansonsten wird sie deaktiviert dargestellt (ab Symcon 6.0) |
| changeOrder (optional) | (default: false) Bei true kann die Reihenfolge der Einträge per Drag & Drop verändert werden. Die Sortierung der Liste nach Spalten ist dann allerdings nicht möglich. (ab Symcon 6.0) |
| loadValuesFromConfiguration (optional) | (default: true) Dieser Parameter gibt an, ob die Liste mit den Werten der Eigenschaft gefüllt werden soll, siehe Speichern und Laden von Listen . Wird der Wert auf false gesetzt, so ist es für einen erfolgreichen Review im Module Store erforderlich, die Liste dennoch im Sinne des Benutzers zu füllen, siehe Reviewrichtlinien Punkt 13 (ab Symcon 6.0) |
Parameter für columns
| Parameter | Beschreibung |
|---|---|
| add (optional) | initialer Wert in dieser Spalte bei einem neu hinzugefügtem Eintrag, notwendig wenn add bei der Liste auf true gesetzt ist. Alternativ kann ein Objekt übergeben werden, welches den Wert automatisch generiert, siehe Parameter für add (ab Symcon 9.1) |
| align (optional) | (default: "left") Ausrichtung der Spalte (ab Symcon 5.2) "left": Inhalt wird linksbündig dargestellt "center": Inhalt wird zentriert dargestellt "right": Inhalt wird rechtsbündig dargestellt |
| caption | Sichtbare Beschriftung einer Spalte |
| confirm (optional) | (default: "") Abfragetext, bevor eine onClick-Aktion ausgeführt wird. Nur wenn die Abfrage mit "Ja" bestätigt wird, wird die Aktion ausgeführt. Ist kein Abfragetext definiert, so wird die Aktion direkt ausgeführt (ab Symcon 5.2) |
| download (optional) | (default: "") Ist dieser Parameter nicht leer und beinhaltet die Ausgabe des onClick-Skriptes dieser Spalte eine Data-URL, so wird die Rückgabe als Textdatei mit dem Namen das download-Parameters heruntergeladen. (ab Symcon 7.1) |
| edit (optional) | Beschreibung eines editierbaren Elements |
| link (optional) | (default: false) Ist dieser Parameter true, dann wird die Ausgabe des onClick-Skriptes dieser Spalte als Link geöffnet. Ist er false, so wird die Ausgabe als Dialog im Konfigurationsformular angezeigt. (ab Symcon 7.1) |
| name | Eindeutiger Name einer Spalte um diese zu referenzieren; der Name darf nicht "rowColor", "editable" oder "deletable" sein, da diese Werte für andere Funktionen belegt sind, siehe Parameter für values |
| onClick (optional) | (default: "") Skript, welches bei einem Klick auf ein Feld dieser Spalte ausgeführt wird. Es hat die gleichen Eigenschaften wie onClick des Button. Das Skript wird nur ausgeführt, sofern dieses Feld nicht leer, also 0, false oder "" ist (ab Symcon 5.2) |
| quickFilter (optional) | (default: false) Bei true wird der Text dieser Spalte beim Schnellfilter in der Suche betrachtet. Sollte der Wert bei allen Spalten auf false gesetzt sein, so wird der Schnellfilter ausgeblendet. (ab Symcon 7.2) |
| sortColumn (optional) | Ist sortColumn gesetzt und wird nach dieser Spalte sortiert, so werden statt den Werten dieser Spalte, die Werte der Spalte mit dem Namen dieses Parameters verglichen |
| save (optional) | (default: true, falls das Element editierbar ist oder add ein Objekt zur automatischen Generierung ist, sonst false) Bei true sollen die Werte dieser Spalte als Modul-Eigenschaften gesichert werden, siehe Speichern und Laden von Listen |
| visible (optional) | (default: true) Bei false wird die Spalte nicht angezeigt |
| width | Breite der Spalte in Pixeln, als CSS-String (z.B. "100px"); eine einzige Spalte darf den Wert "auto" haben, wodurch die Breite dieser Spalte den restlich verfügbaren Platz nutzt |
Parameter für edit
| Parameter | Beschreibung |
|---|---|
| type | Typ der Darstellung, entsprechend der möglichen Eingaben: CheckBox, IntervalBox, NumberSpinner, PasswordTextBox, Select, SelectCategory, SelectColor, SelectEvent, SelectFile, SelectInstance, SelectLink, SelectMedia, SelectObject, SelectScript, SelectVariable, ValidationTextBox, List, Tree |
| Weitere Parameter | Die weiteren Parameter ergeben sich je nach gewähltem Typ; die Parameter "name" und "caption" des Typs werden ignoriert |
Wird der "type" List oder Tree verwendet, so wird der Wert dieser Spalte nicht noch einmal JSON-codiert. Es ist also lediglich erforderlich den Wert der übergeordneten Liste einmalig zu parsen. Jede Unterliste bzw. Unterbaum steht dann direkt als Objekt zur Verfügung. Analog müssen die Werte in "values" auch nicht doppelt codiert werden.
Der Parameter "add" der Spalte wird entsprechend der Lokalisierung übersetzt, sofern der "type" von "edit" ValidationTextBox oder PasswordTextBox ist oder "edit" gar nicht gesetzt ist
Es ist möglich mit der Funktion UpdateFormField nur Teile von von columns oder values zu aktualisieren, indem eine Punktnotation verwendet wird. In dem Fall wird als Ziel columns.x.y bzw. values.x.y verwendet. x bezieht sich dabei auf den Index der betroffenen Spalte bzw. des betroffenen Wertes und y auf den Namen des Feldes. Es ist auch möglich einen einzelne Spalte bzw. einen einzelnen Wert komplett zu bearbeiten indem als Ziel columns.x bzw. values.x verwendet wird. Um also beispielsweise die Breite der zweiten Spalte anzupassen, kann der Befehl $this->UpdateFormField('list', 'columns.1.width', '200px'); verwendet werden.
Parameter für add
Statt eines festen Wertes kann der Parameter add einer Spalte auch ein Objekt sein, welches beschreibt, mit welcher Strategie der Wert für einen neu hinzugefügten Eintrag automatisch generiert wird (ab Symcon 9.1). Der Wert wird beim Hinzufügen des Eintrages generiert und anschließend wie ein regulärer Wert behandelt. Der generierte Wert ist innerhalb der Spalte eindeutig: Stimmt ein zufälliger Wert mit dem Wert eines bestehenden Eintrages überein, so wird ein neuer Wert generiert. Generierte Werte werden nicht übersetzt.
| Parameter | Beschreibung |
|---|---|
| strategy | Strategie der Generierung: "increment": Der höchste numerische Wert dieser Spalte über alle Einträge der Liste wird um step erhöht. Nicht numerische Werte werden ignoriert. Existiert noch kein numerischer Wert, so wird start bzw. ohne start der Wert step verwendet. Ist start gesetzt, so wird nie ein Wert kleiner als start generiert (bei negativem step nie ein größerer) "random-string": Eine zufällige Zeichenkette aus den Zeichen a-z, A-Z und 0-9 mit der Länge length "random-integer": Eine zufällige ganze Zahl zwischen min und max "guid": Eine zufällige GUID (UUID Version 4), z.B. "{3F2504E0-4F89-4D3A-9A0C-0305E82C3301}" |
| step (optional) | (default: 1) Schrittweite, um welche der höchste Wert erhöht wird, nur für die strategy "increment"; muss eine Zahl ungleich 0 sein |
| start (optional) | Wert des ersten Eintrages und Untergrenze aller folgenden Werte (Obergrenze bei negativem step), nur für die strategy "increment"; muss eine Zahl sein |
| length (optional) | (default: 32) Anzahl der Zeichen der generierten Zeichenkette, nur für die strategy "random-string" |
| min (optional) | (default: 0) Untere Grenze (inklusive) der zufälligen ganzen Zahl, nur für die strategy "random-integer"; muss kleiner als max sein |
| max (optional) | (default: 2147483647) Obere Grenze (inklusive) der zufälligen ganzen Zahl, nur für die strategy "random-integer"; muss größer als min sein |
Damit generierte Werte erhalten bleiben, werden Spalten mit einem solchen add-Wert standardmäßig gespeichert, d.h. der Parameter "save" ist für diese Spalten standardmäßig true. Fehlt einem geladenen Eintrag der Wert in einer solchen Spalte, z.B. weil die Spalte nachträglich hinzugefügt wurde, so wird der Wert beim Laden nach der gleichen Strategie generiert. Auch der Standardwert, den on-Aktionen erhalten, wenn kein Eintrag ausgewählt ist, wird nach der Strategie generiert. Kann kein eindeutiger Wert generiert werden, weil bereits alle möglichen Werte verwendet werden, z.B. bei "random-integer" mit einem kleinen Bereich zwischen min und max, so schlägt das Hinzufügen mit einer Fehlermeldung fehl.
// Spalten mit automatisch generierten Werten
{
"caption": "ID",
"name": "ID",
"width": "50px",
"add": { "strategy": "increment", "step": 10 }
}, {
"caption": "Token",
"name": "Token",
"width": "auto",
"add": { "strategy": "random-string", "length": 16 },
"edit": { "type": "ValidationTextBox" }
}, {
"caption": "Zufallszahl",
"name": "Number",
"width": "100px",
"add": { "strategy": "random-integer", "min": 1, "max": 100 },
"edit": { "type": "NumberSpinner" }
}, {
"caption": "GUID",
"name": "GUID",
"width": "300px",
"add": { "strategy": "guid" }
}
Die strategy "increment" ermittelt den nächsten Wert aus den aktuellen Einträgen. Wird der Eintrag mit dem höchsten Wert gelöscht, so wird dessen Wert beim nächsten Hinzufügen erneut vergeben. Soll ein Wert nie wiederverwendet werden, z.B. weil er als dauerhafte ID gegenüber einem externen System dient, so kann sich das Modul den höchsten jemals vergebenen Wert merken und ihn über start vorgeben.
// Gelöschte IDs werden nicht erneut vergeben
public function GetConfigurationForm(): string
{
$form = json_decode(file_get_contents(__DIR__ . '/form.json'), true);
// Das Attribut HighestID wird in ApplyChanges auf den höchsten Wert der Liste aktualisiert, sinkt aber nie
$form['elements'][0]['columns'][0]['add'] = ['strategy' => 'increment', 'start' => $this->ReadAttributeInteger('HighestID') + 1];
return json_encode($form);
}
Parameter für sort
| Parameter | Beschreibung |
|---|---|
| column | Name der Spalte, nach welcher die Liste sortiert wird |
| direction | Die Richtung der Sortierung; "ascending" für eine aufsteigende Sortierung und "descending" für eine absteigende Sortierung |
Parameter für values
| Parameter | Beschreibung |
|---|---|
| deletable (optional) | (default: true) Bei false kann die Zeile nicht gelöscht werden (ab Symcon 5.4) |
| editable (optional) | (default: true) Bei false kann die Zeile nicht editiert werden, obwohl die Liste an sich editierbare Spalten besitzt (ab Symcon 5.4) |
| rowColor (optional) | (default: transparent) Hintergrundfarbe der Zeile als Hex-Code (Defaultfarben s.u.), leerer String für Transparenz |
| icons (optional) | (default: {}) Ein Objekt welches die verwendeten Icons für jede Spalte beinhaltet. Dabei gibt der Schlüssel jeweils den Namen der Spalte an und der Wert den Namen des verwendeten Icons. Ist für eine Spalte kein Eintrag im Objekt vorhanden, so wird für diese Spalte kein Icon angezeigt. (ab Symcon 9.0) |
| Weitere Parameter (optional) | (default: "") Für jeden initialen Eintrag der Liste werden hier die Werte zu allen Spalten definiert. Hierfür wird für jede Spalte ein Parameter mit dem Namen der Spalte eingetragen. Die Belegung des Parameters entspricht dem Wert dieser Spalte bei dem entsprechenden Eintrag. |
| Farbe | Hex-Code |
|---|---|
| Hellgrün | #C0FFC0 |
| Lila | #C0C0FF |
| Gelb | #FFFFC0 |
| Grau | #DFDFDF |
| Rot | #FFC0C0 |
Was die einzelnen Farben bei Meldungen und im Konfigurator bedeuten kann unter den Farbcodes für Meldungen und Konfiguratoren nachgelesen werden.
Alle von iron-icon unterstützen Icons sind nutzbar: Iron Icons Demo
Darüber hinaus können folgende Symcon-spezifischen Icons genutzt werden:

Speichern und Laden von Listen
Beim Speichern der Liste werden alle Listenelemente, die editierbar sind oder den Paramter save gesetzt haben, als Modul-Eigenschaften gesichert.
Wird die Liste erneut geladen und ist der Parameter loadValuesFromConfiguration nicht auf false gesetzt, so werden zuerst die Werte eingetragen, die als Modul-Eigenschaften gesichert wurden. Steht loadValuesFromConfiguration auf false, werden keine Werte aus den Eigenschaften geladen sondern nur wie in den weiteren Schritten beschrieben geladen. Sollen dennoch Werte aus der Eigenschaft als Grundlage verwendet werden, so müssen diese selbstständig in values eingetragen werden. Die weiteren Elemente, inklusive der Farbe, werden mit den initialen Werten aus values aufgefüllt.
Existieren mehr Zeilen als Elemente in values, so werden Elemente der überzähligen Zeilen, welche nicht als Modul-Eigenschaften gesichert waren, mit dem Initialwert add der entsprechenden Spalte gefüllt.
Ausgewählte Zeile als Variable in on-Aktionen
In der Definition des Konfigurationsformulares können die Werte der Tabelle als Variable $Name verwendet werden. Auf das Objekt kann wie auf ein Array zugegriffen werden. Wird auf das entsprechende Objekt mit einem String-Index zugegriffen, so wird der entsprechende Wert wie in values definiert der ausgewählten Zeile zurückgegeben. Wird mit einem numerischen Index zugegriffen oder das Objekt iteriert, so wird die entsprechende Zeile zurückgegeben, deren einzelne Parameter widerum per String-Index referenziert werden können.
Beispiel:
//Gebe den Namen der aktuell gewählte Zeile der Tabelle devices aus
{ "type": "Button", "caption": "Ausgabe", "onClick": "print_r($devices['name']);" }
//Gebe den Namen der ersten Zeile der Tabelle devices aus
{ "type": "Button", "caption": "Ausgabe", "onClick": "print_r($devices[0]['name']);" }
Auf die Auswahl reagieren
Über den Parameter onSelectionChanged kann das Modul darauf reagieren, dass der Benutzer eine andere Zeile der Liste auswählt (ab Symcon 9.1). Typische Anwendungsfälle sind:
- Buttons aktivieren, die sich auf die ausgewählte Zeile beziehen, z.B. "Gerät testen"
- Details der ausgewählten Zeile in anderen Formularfeldern anzeigen, z.B. in einem Label
- Abhängige Daten laden, z.B. die Kanäle des ausgewählten Gerätes in einer zweiten Liste
Die Werte der neu ausgewählten Zeile stehen wie unter Ausgewählte Zeile als Variable in on-Aktionen beschrieben über $(Name der Liste)['Name der Spalte'] zur Verfügung, $id und alle anderen Formularfelder wie gewohnt. Da das Skript nicht innerhalb des Moduls ausgeführt wird, ruft es typischerweise eine Funktion des Moduls auf, welche die anderen Formularfelder per UpdateFormField anpasst.
| Situation | onSelectionChanged |
|---|---|
| Klick auf eine andere Zeile | Wird ausgeführt |
| Wechsel der Zeile per Pfeiltaste | Wird ausgeführt |
| Klick auf die bereits ausgewählte Zeile | Wird nicht ausgeführt |
| Aufheben der Auswahl, z.B. durch einen Klick auf eine freie Fläche der Liste oder Löschen der ausgewählten Zeile | Wird nicht ausgeführt |
| Hinzufügen, Bearbeiten oder Verschieben einer Zeile | Wird nicht ausgeführt, stattdessen onAdd, onEdit bzw. onChangeOrder |
| Änderung von values per UpdateFormField | Wird nicht ausgeführt. Die Auswahl bleibt an derselben Position erhalten, sofern dort noch eine Zeile existiert, ansonsten wird sie aufgehoben |
Das onClick einer Spalte wird hingegen bei jedem Klick auf ein nicht-leeres Feld dieser Spalte ausgeführt, auch wenn die Zeile bereits ausgewählt ist. Wählt ein Klick eine andere Zeile aus, so werden beide Skripte ausgeführt. Für Aktionen, die nur von der ausgewählten Zeile und nicht von der angeklickten Spalte abhängen, ist onSelectionChanged daher die bessere Wahl.
Hinweise:
- Da das Aufheben der Auswahl onSelectionChanged nicht auslöst, sollten Skripte, die sich auf die Auswahl beziehen, z.B. das onClick eines Buttons, damit rechnen, dass keine Zeile ausgewählt ist. $(Name der Liste)['Name der Spalte'] liefert dann den Wert add der Spalte.
- Das Skript wird bei jedem Wechsel ausgeführt, z.B. auch beim Durchblättern per Pfeiltaste. Es sollte daher schnell sein. Aufwändige Aktionen gehören in einen Button.
- Eine Ausgabe des Skriptes wird wie beim Button als Meldung angezeigt.
Beispiel: Eine Liste von Geräten, deren Details und Kanäle bei Auswahl eines Gerätes angezeigt werden. Der Button "Gerät testen" wird erst aktiviert, wenn ein Gerät ausgewählt ist.
// Beispiel: form.json
{
"actions": [
{
"type": "List",
"name": "Devices",
"caption": "Geräte",
"rowCount": 5,
"columns": [
{ "caption": "Name", "name": "Name", "width": "auto", "add": "" },
{ "caption": "Adresse", "name": "Address", "width": "150px", "add": "" }
],
"values": [],
"onSelectionChanged": "DEV_UISelectDevice($id, $Devices['Address']);"
},
{ "type": "Label", "name": "DeviceDetails", "caption": "Bitte ein Gerät auswählen" },
{
"type": "List",
"name": "Channels",
"caption": "Kanäle",
"rowCount": 3,
"columns": [
{ "caption": "Kanal", "name": "Channel", "width": "auto", "add": "" }
],
"values": []
},
{
"type": "Button",
"name": "TestButton",
"caption": "Gerät testen",
"enabled": false,
"onClick": "DEV_UITestDevice($id, $Devices['Address']);"
}
]
}
// Beispiel: module.php
<?php
declare(strict_types=1);
class DeviceOverview extends IPSModule
{
// In einem echten Modul stammt diese Liste z.B. aus einer Suche im Netzwerk
private const DEVICES = [
'192.168.1.20' => ['Name' => 'Wohnzimmer', 'Channels' => ['Temperatur', 'Luftfeuchte']],
'192.168.1.21' => ['Name' => 'Keller', 'Channels' => ['Temperatur', 'Wasserstand', 'Pumpe']]
];
public function GetConfigurationForm()
{
$form = json_decode(file_get_contents(__DIR__ . '/form.json'), true);
$values = [];
foreach (self::DEVICES as $address => $device) {
$values[] = ['Name' => $device['Name'], 'Address' => $address];
}
$form['actions'][0]['values'] = $values;
return json_encode($form);
}
// onSelectionChanged der Liste Devices: Zeigt die Details der ausgewählten Zeile an
public function UISelectDevice(string $Address)
{
$device = self::DEVICES[$Address] ?? ['Name' => '', 'Channels' => []];
$this->UpdateFormField('DeviceDetails', 'caption', sprintf('%s (%s) mit %d Kanälen', $device['Name'], $Address, count($device['Channels'])));
$channels = [];
foreach ($device['Channels'] as $channel) {
$channels[] = ['Channel' => $channel];
}
$this->UpdateFormField('Channels', 'values', json_encode($channels));
$this->UpdateFormField('TestButton', 'enabled', true);
}
// onClick des Buttons "Gerät testen"
public function UITestDevice(string $Address)
{
if ($Address == '') {
echo 'Bitte ein Gerät auswählen';
return;
}
echo Sys_Ping($Address, 1000) ? 'Das Gerät antwortet' : 'Das Gerät antwortet nicht';
}
}
Mehrere Objekte hinzufügen
Besitzt eine Liste nur eine einzige editierbare Spalte vom Typ SelectObject, SelectCategory, SelectEvent, SelectInstance, SelectLink, SelectMedia, SelectScript oder SelectVariable und ist form nicht gesetzt, so öffnet der "Hinzufügen"-Button direkt die Objektauswahl statt des Dialogs. Zusätzlich können Objekte per Drag & Drop auf der Liste abgelegt werden. Ob dabei mehrere Objekte gleichzeitig hinzugefügt werden können, bestimmt multiAdd.
Wird multiAdd explizit auf true gesetzt, so wird die Objektauswahl auch dann direkt geöffnet, wenn die Liste weitere editierbare Spalten besitzt oder form gesetzt ist (ab Symcon 9.1). Das bietet sich insbesondere an, wenn das Objekt der wesentliche Bestandteil einer Zeile ist und die weiteren Parameter eher sekundär sind. Der Benutzer kann so viele Objekte in einem Schritt hinzufügen und muss nur die Zeilen nachträglich bearbeiten, die vom Standard abweichen sollen.
| Aktion | Verhalten |
|---|---|
| Hinzufügen | Die Objektauswahl der ersten sichtbaren Spalte, deren edit eine Objektauswahl ist, wird geöffnet. Für jedes gewählte Objekt wird eine eigene Zeile hinzugefügt. Alle weiteren Werte der Zeile erhalten ihren add-Wert. onAdd wird einmalig für alle hinzugefügten Zeilen ausgeführt |
| Drag & Drop | Die abgelegten Objekte werden wie beim Hinzufügen über die Objektauswahl hinzugefügt. Objekte, welche die Spalte nicht akzeptiert, werden übersprungen |
| Bearbeiten | Der Dialog wird wie gewohnt geöffnet, sodass die weiteren Werte im Nachhinein angepasst werden können |
Ist form gesetzt, so muss das Formular ein Element mit dem Namen dieser Spalte enthalten, welches eine Objektauswahl bietet, z.B. eine SelectVariable. Wird das Formular per PHP-Code erzeugt, so wird dieser vor dem Öffnen der Objektauswahl ausgeführt. Wie beim Bestätigen des Dialogs werden alle benannten Elemente des Formulars in die Zeile geschrieben, siehe Hinweise zu individuellen Formularen. Existiert keine passende Spalte oder enthält das Formular kein passendes Element, so wird eine Fehlermeldung angezeigt und stattdessen der Dialog geöffnet.
// Beispiel: Variablen überwachen, ob sie regelmäßig aktualisiert werden
// Da multiAdd explizit true ist, öffnet "Hinzufügen" direkt die Objektauswahl, obwohl die Liste weitere editierbare Spalten besitzt.
// Das ist insbesondere dann ideal, wenn die weiteren Parameter eher sekundär sind: Für die meisten Variablen passen
// die Standardwerte aus add, sodass beliebig viele Variablen in einem Schritt hinzugefügt werden können.
// Nur einzelne Zeilen, die vom Standard abweichen sollen, werden anschließend über den Bearbeiten-Dialog angepasst.
{
"type": "List",
"name": "Variables",
"caption": "Überwachte Variablen",
"rowCount": 10,
"add": true,
"delete": true,
"multiAdd": true,
"columns": [{
"caption": "Variable",
"name": "VariableID",
"width": "auto",
"add": 0,
"edit": { "type": "SelectVariable" }
}, {
"caption": "Timeout",
"name": "Timeout",
"width": "100px",
"add": 60,
"edit": { "type": "NumberSpinner", "suffix": "min", "minimum": 1 }
}, {
"caption": "Aktiv",
"name": "Active",
"width": "60px",
"add": true,
"edit": { "type": "CheckBox" }
}]
}
Individuelle Formulare zum Bearbeiten
Standardmäßig wird beim Hinzufügen oder Bearbeiten einer Zeile ein Dialog angezeigt, welcher für jede Spalte mit edit-Parameter genau ein Eingabefeld enthält. Über den Parameter form der Liste kann stattdessen ein beliebiges Formular für diesen Dialog definiert werden (ab Symcon 7.0). Das Formular kann alle Konfigurationselemente enthalten, die auch im regulären Konfigurationsformular möglich sind, z.B. RowLayout, ExpansionPanel, PopupButton, ein Select mit Elementen je Option oder eine weitere Liste. Jedes benannte Element des Formulars wird zu einem Wert der Zeile, unabhängig davon, ob eine Spalte mit diesem Namen existiert.
Ein individuelles Formular bietet sich an, wenn
- eine Zeile mehr Einstellungen besitzt, als sinnvoll als Spalten angezeigt werden können. Die Liste zeigt dann nur eine Übersicht und alle Details werden im Dialog bearbeitet
- die Eingabefelder vom Typ der Zeile abhängen, z.B. benötigt ein Rollladen andere Einstellungen als ein Dimmer
- die Eingabefelder Hinweistexte, Gruppierungen, Validierung oder Abhängigkeiten untereinander (onChange) benötigen
- eine Zeile verschachtelte Daten besitzt, z.B. eine Liste von Übersetzungen oder Rollen je Zeile
- die möglichen Werte erst zur Laufzeit bekannt sind, z.B. Auswahloptionen, die von anderen Instanzen oder vom Wert der Zeile abhängen
- einzelne Einträge einer Liste bearbeitet werden sollen, die vom Modul verwaltet wird, z.B. die Parameter eines Gerätes oder Zugriffstoken. Statt eines separaten PopupButton mit einem Select zur Auswahl des Eintrages genügt eine Liste mit form und onEdit. Der Benutzer klickt direkt auf das Bearbeiten-Symbol der gewünschten Zeile
Statisches Formular oder PHP-Code
Das Formular wird analog zum Formular für Aktionen definiert:
| form | Verhalten |
|---|---|
| Array von Konfigurationselementen | Das Formular ist für alle Zeilen gleich. Es wird beim ersten Öffnen des Dialogs erstellt und danach wiederverwendet |
| PHP-Code als String oder Array aus Strings | Der Code wird bei jedem Öffnen des Dialogs ausgeführt und gibt das Array von Konfigurationselementen per return zurück. So kann für jede Zeile ein eigenes Formular erzeugt werden, z.B. abhängig vom Typ der Zeile |
Der PHP-Code wird wie ein onClick-Skript eines Button als eigenständiges Skript ausgeführt und nicht innerhalb des Moduls. $this steht daher nicht zur Verfügung, Funktionen des Moduls werden über ihren Präfix aufgerufen. Folgende Variablen stehen zur Verfügung:
| Variable | Inhalt |
|---|---|
| $id | ID der Instanz |
| $(Name der Liste) | Die Liste wie unter Ausgewählte Zeile als Variable in on-Aktionen beschrieben. Ein String-Index liefert den Wert der zu bearbeitenden Zeile, z.B. $Devices['Type']. Beim Hinzufügen liefert er stattdessen den add-Wert der Spalte. Per numerischem Index oder foreach sind alle Zeilen verfügbar |
| $(Name eines Elements) | Der aktuelle, ggf. noch nicht übernommene Wert jedes weiteren benannten Elements des Konfigurationsformulars |
Der Rückgabewert kann ein PHP-Array oder ein mit json_decode dekodiertes Formular sein. Jede weitere Ausgabe des Skriptes, z.B. durch echo oder eine PHP-Warnung, macht das Ergebnis ungültig. Fehler werden anstelle des Formulars im Dialog angezeigt. Da der Code bei jedem Öffnen des Dialogs ausgeführt wird, sollte er schnell sein.
Bewährt hat sich folgendes Vorgehen, welches auch die in Symcon integrierten Module nutzen: Die form.json enthält das Formular der Zeilen statisch als Vorlage. GetConfigurationForm ersetzt es durch einen kurzen PHP-Code, welcher eine öffentliche Funktion des Moduls mit den benötigten Werten der Zeile aufruft, z.B. "return json_decode(SHD_UIMotorForm($id, $Motors['WeatherStationID'] ?? 0), true);". Diese Funktion lädt die Vorlage, passt sie für die Zeile an (z.B. Optionen und Sichtbarkeit) und gibt sie als JSON-String zurück, siehe Beispiel 4.
Ablauf beim Bearbeiten
| Aktion | Verhalten |
|---|---|
| Hinzufügen | Das Formular wird geladen. Jedes Formularfeld, zu dem eine Spalte mit gleichem Namen existiert, erhält den add-Wert dieser Spalte. Alle übrigen Felder behalten ihren aktuellen Wert, siehe Hinweise |
| Bearbeiten | Das Formular wird geladen. Jedes Formularfeld erhält den Wert mit gleichem Namen aus der Zeile, sowohl Werte von Spalten als auch Werte ohne Spalte |
| Bestätigen | Der Dialog kann nur bestätigt werden, wenn alle sichtbaren Felder gültig sind, z.B. entsprechend validate einer ValidationTextBox. Anschließend wird der Wert jedes benannten Elements unter seinem Namen in die Zeile geschrieben, auch aus RowLayout, ColumnLayout, ExpansionPanel, PopupButton, den items einer CheckBox und den items der Optionen eines Select. Beim Bearbeiten bleiben alle übrigen Werte der Zeile erhalten, beim Hinzufügen erhalten Spalten ohne passendes Formularfeld ihren add-Wert. Danach wird onAdd bzw. onEdit ausgeführt |
| Abbrechen | Die Zeile bleibt unverändert, onAdd bzw. onEdit wird nicht ausgeführt |
| onAdd, onEdit, onDelete | Über $(Name der Liste)['Name'] stehen alle Werte der Zeile zur Verfügung, auch Werte von Formularfeldern ohne Spalte |
| Übernehmen | Werte von Spalten werden entsprechend ihres save-Parameters gespeichert. Werte ohne passende Spalte werden immer gespeichert |
| Laden | Gespeicherte Werte ohne Spalte bleiben in der Zeile erhalten und stehen beim nächsten Bearbeiten wieder zur Verfügung |
Ist form gesetzt, so wird immer ein Bearbeiten-Symbol angezeigt, außer für Zeilen mit "editable": false. Die edit-Parameter der Spalten werden für den Dialog nicht verwendet, bestimmen aber weiterhin die Darstellung in der Liste, z.B. die Beschriftung der Option eines Select oder den Namen eines Objektes, und ob die Spalte standardmäßig gespeichert wird. Sichtbare Spalten mit einer CheckBox als edit können weiterhin direkt in der Liste umgeschaltet werden, wobei onEdit ohne Dialog ausgeführt wird. Das direkte Hinzufügen über die Objektauswahl sowie das Hinzufügen per Drag & Drop stehen mit form nur zur Verfügung, wenn multiAdd explizit auf true gesetzt ist, siehe Mehrere Objekte hinzufügen.
Hinweise zu individuellen Formularen
- Spalten ohne edit werden standardmäßig nicht gespeichert. Wird eine solche Spalte über das Formular befüllt, muss "save": true gesetzt werden, da ihr Wert sonst beim Übernehmen verloren geht. Werte ohne Spalte werden hingegen immer gespeichert.
- Ein statisches Formular wird wiederverwendet. Felder, für welche die Zeile bzw. beim Hinzufügen die Spalten keinen Wert liefern, behalten den Wert des zuletzt geöffneten Dialogs. Auch Änderungen über UpdateFormField, z.B. an visible oder options, bleiben erhalten. Daher sollte für jedes Formularfeld eine Spalte mit add-Wert existieren, bei Bedarf unsichtbar mit "visible": false und "save": true. Alternativ wird das Formular per PHP-Code erzeugt und Sichtbarkeit sowie Optionen dort anhand der Zeile gesetzt.
- Enthält das Formular eine List oder einen Tree, so sollte eine Spalte mit gleichem Namen und "edit": { "type": "List" } bzw. "edit": { "type": "Tree" } existieren, bei Bedarf unsichtbar. Nur dann steht der Wert in der Zeile und in der Eigenschaft als Array zur Verfügung, ansonsten als JSON-codierter String.
- Beim Hinzufügen enthält $(Name der Liste)['Name'] den add-Wert der Spalte. Für Werte ohne Spalte oder ohne add-Wert ist der Index nicht gesetzt. Im PHP-Code sollte daher ein Standardwert per ?? angegeben werden, z.B. $Devices['Type'] ?? 0.
- Skripte der Elemente im Dialog, z.B. onChange, erhalten $id und die Werte der Elemente des Dialogs als Variablen, nicht jedoch die Liste. Über UpdateFormField kann das Modul die Elemente des geöffneten Dialogs über ihren Namen anpassen, z.B. Optionen oder Sichtbarkeit. Die Namen der Elemente im Dialog sollten sich daher von den Namen der übrigen Elemente des Konfigurationsformulars unterscheiden.
- Das Bestätigen des Dialogs ändert nur die Liste im Konfigurationsformular. Gespeichert wird erst beim Übernehmen. Soll eine Änderung sofort wirken, z.B. an ein Gerät gesendet werden, so muss dies in onAdd bzw. onEdit geschehen, siehe Beispiel 3.
Beispiele für individuelle Formulare
Beispiel 1: Statisches Formular für Zeilen mit vielen Einstellungen. Die Liste zeigt nur eine Übersicht. Die Spalten "Name" und "Limit" besitzen kein edit und benötigen daher "save": true. Die Einstellungen, die nur im Dialog sichtbar sind, besitzen unsichtbare Spalten, damit sie beim Hinzufügen auf ihren add-Wert gesetzt werden.
// Beispiel 1: Statisches Formular für Zeilen mit vielen Einstellungen
{
"type": "List",
"name": "Sensors",
"caption": "Sensoren",
"rowCount": 5,
"add": true,
"delete": true,
"columns": [{
"caption": "Aktiv",
"name": "Active",
"width": "60px",
"add": true,
"edit": { "type": "CheckBox" }
}, {
"caption": "Name",
"name": "Name",
"width": "auto",
"add": "",
"save": true
}, {
"caption": "Variable",
"name": "VariableID",
"width": "250px",
"add": 0,
"edit": { "type": "SelectVariable" }
}, {
"caption": "Grenzwert",
"name": "Limit",
"width": "100px",
"add": 25,
"save": true
}, {
"name": "Hysteresis",
"visible": false,
"add": 0.5,
"save": true
}, {
"name": "Delay",
"visible": false,
"add": 60,
"save": true
}, {
"name": "Message",
"visible": false,
"add": "",
"save": true
}],
"form": [{
"type": "RowLayout",
"items": [
{ "type": "CheckBox", "name": "Active", "caption": "Aktiv" },
{ "type": "ValidationTextBox", "name": "Name", "caption": "Name", "validate": "^.+$" }
]
}, {
"type": "SelectVariable",
"name": "VariableID",
"caption": "Variable",
"validVariableTypes": [1, 2],
"width": "400px"
}, {
"type": "RowLayout",
"items": [
{ "type": "NumberSpinner", "name": "Limit", "caption": "Grenzwert", "digits": 1 },
{ "type": "NumberSpinner", "name": "Hysteresis", "caption": "Hysterese", "digits": 1, "minimum": 0 }
]
}, {
"type": "ExpansionPanel",
"caption": "Erweitert",
"items": [
{ "type": "NumberSpinner", "name": "Delay", "caption": "Verzögerung", "suffix": "s", "minimum": 0 },
{ "type": "ValidationTextBox", "name": "Message", "caption": "Meldungstext", "multiline": true, "width": "400px" }
]
}]
}
Beispiel 2: Unterschiedliche Felder je nach Typ der Zeile, ohne PHP-Code (ab Symcon 9.1). Die Felder hängen an den Optionen des Select und werden nur angezeigt, solange die entsprechende Option gewählt ist. Die Werte der Felder der übrigen Optionen bleiben dabei erhalten und werden ebenfalls in der Zeile gespeichert.
// Beispiel 2: Felder abhängig vom Typ der Zeile
{
"type": "List",
"name": "Devices",
"caption": "Geräte",
"rowCount": 5,
"add": true,
"delete": true,
"columns": [{
"caption": "Name",
"name": "Name",
"width": "auto",
"add": "",
"save": true
}, {
"caption": "Typ",
"name": "Type",
"width": "150px",
"add": 0,
"edit": {
"type": "Select",
"options": [
{ "caption": "Schalter", "value": 0 },
{ "caption": "Dimmer", "value": 1 },
{ "caption": "Rollladen", "value": 2 }
]
}
}, {
"caption": "Statusvariable",
"name": "StatusID",
"width": "250px",
"add": 0,
"edit": { "type": "SelectVariable" }
},
{ "name": "MinimumLevel", "visible": false, "add": 0, "save": true },
{ "name": "RampTime", "visible": false, "add": 1, "save": true },
{ "name": "RunTimeUp", "visible": false, "add": 30, "save": true },
{ "name": "RunTimeDown", "visible": false, "add": 30, "save": true },
{ "name": "Invert", "visible": false, "add": false, "save": true }],
"form": [{
"type": "ValidationTextBox",
"name": "Name",
"caption": "Name"
}, {
"type": "SelectVariable",
"name": "StatusID",
"caption": "Statusvariable"
}, {
"type": "Select",
"name": "Type",
"caption": "Typ",
"options": [{
"caption": "Schalter",
"value": 0
}, {
"caption": "Dimmer",
"value": 1,
"items": [
{ "type": "NumberSpinner", "name": "MinimumLevel", "caption": "Minimale Helligkeit", "suffix": "%", "minimum": 0, "maximum": 100 },
{ "type": "NumberSpinner", "name": "RampTime", "caption": "Dimmgeschwindigkeit", "suffix": "s", "digits": 1, "minimum": 0 }
]
}, {
"caption": "Rollladen",
"value": 2,
"items": [{
"type": "RowLayout",
"items": [
{ "type": "NumberSpinner", "name": "RunTimeUp", "caption": "Fahrzeit auf", "suffix": "s", "minimum": 1 },
{ "type": "NumberSpinner", "name": "RunTimeDown", "caption": "Fahrzeit ab", "suffix": "s", "minimum": 1 }
]
}, {
"type": "CheckBox",
"name": "Invert",
"caption": "Position invertieren"
}]
}]
}]
}
Beispiel 3: Ein eigenes Formular je Zeile, erzeugt durch das Modul. Die Liste zeigt die Parameter eines Gerätes, jede Zeile benötigt ein anderes Eingabeelement: eine CheckBox, einen NumberSpinner mit Grenzen, ein Select mit Optionen oder ein Textfeld. Die Liste steht unter actions und wird daher nicht als Eigenschaft gespeichert. Ihre Einträge werden in GetConfigurationForm gefüllt und jede Änderung wird per onEdit direkt übernommen.
// Beispiel 3: form.json
{
"actions": [{
"type": "List",
"name": "Parameters",
"caption": "Geräteparameter",
"rowCount": 10,
"columns": [
{ "name": "Ident", "visible": false },
{ "caption": "Parameter", "name": "Caption", "width": "auto" },
{ "caption": "Wert", "name": "DisplayValue", "width": "200px" },
{ "name": "Value", "visible": false }
],
"values": [],
"form": "return json_decode(DEV_UIParameterForm($id, $Parameters['Ident']), true);",
"onEdit": "DEV_WriteParameter($id, $Parameters['Ident'], $Parameters['Value']);"
}]
}
// Beispiel 3: module.php
<?php
declare(strict_types=1);
class ParameterDevice extends IPSModule
{
// In einem echten Modul liefert das Gerät diese Definition
private const PARAMETERS = [
'LedMode' => ['caption' => 'LED-Modus', 'type' => 'enum', 'options' => [0 => 'Aus', 1 => 'Ein', 2 => 'Status']],
'Brightness' => ['caption' => 'Helligkeit', 'type' => 'number', 'minimum' => 0, 'maximum' => 100, 'suffix' => '%'],
'ChildLock' => ['caption' => 'Kindersicherung', 'type' => 'bool'],
'Label' => ['caption' => 'Beschriftung', 'type' => 'string']
];
public function Create()
{
//Never delete this line!
parent::Create();
$this->RegisterAttributeString('ParameterValues', '{"LedMode": 2, "Brightness": 80, "ChildLock": false, "Label": ""}');
}
public function GetConfigurationForm()
{
$form = json_decode(file_get_contents(__DIR__ . '/form.json'), true);
$form['actions'][0]['values'] = $this->GetParameterRows();
return json_encode($form);
}
// Wird vom PHP-Code in "form" aufgerufen und liefert das Formular für die bearbeitete Zeile
public function UIParameterForm(string $Ident): string
{
$parameter = self::PARAMETERS[$Ident];
// Das Element heißt wie die Spalte "Value" und erhält daher automatisch den Wert der Zeile
$element = ['name' => 'Value', 'caption' => $parameter['caption']];
switch ($parameter['type']) {
case 'bool':
$element['type'] = 'CheckBox';
break;
case 'number':
$element['type'] = 'NumberSpinner';
$element['minimum'] = $parameter['minimum'];
$element['maximum'] = $parameter['maximum'];
$element['suffix'] = $parameter['suffix'];
break;
case 'enum':
$element['type'] = 'Select';
$element['options'] = [];
foreach ($parameter['options'] as $value => $caption) {
$element['options'][] = ['caption' => $caption, 'value' => $value];
}
break;
default:
$element['type'] = 'ValidationTextBox';
break;
}
return json_encode([$element]);
}
// Wird per onEdit nach dem Bestätigen des Dialogs aufgerufen
public function WriteParameter(string $Ident, $Value)
{
// In einem echten Modul wird der Wert hier an das Gerät gesendet
$values = json_decode($this->ReadAttributeString('ParameterValues'), true);
$values[$Ident] = $Value;
$this->WriteAttributeString('ParameterValues', json_encode($values));
// Die Liste aktualisieren, damit der formatierte Wert angezeigt wird
$this->UpdateFormField('Parameters', 'values', json_encode($this->GetParameterRows()));
}
private function GetParameterRows(): array
{
$values = json_decode($this->ReadAttributeString('ParameterValues'), true);
$rows = [];
foreach (self::PARAMETERS as $ident => $parameter) {
$value = $values[$ident];
switch ($parameter['type']) {
case 'bool':
$display = $value ? 'Ja' : 'Nein';
break;
case 'number':
$display = $value . ' ' . $parameter['suffix'];
break;
case 'enum':
$display = $parameter['options'][$value];
break;
default:
$display = $value;
break;
}
$rows[] = [
'Ident' => $ident,
'Caption' => $parameter['caption'],
'DisplayValue' => $display,
'Value' => $value
];
}
return $rows;
}
}
Beispiel 4: Vorlage in der form.json, welche per PHP-Code für jede Zeile angepasst wird. Die Auswahl der Wetterstation wird zur Laufzeit gefüllt und die Auswahl des Sensors hängt von der Wetterstation der Zeile ab. Wird im Dialog eine andere Wetterstation gewählt, so passt onChange die Sensorauswahl per UpdateFormField an. Die Spalte "WeatherStationID" besitzt ein edit vom Typ SelectInstance, damit die Liste den Namen der Instanz anzeigt und die Spalte gespeichert wird.
// Beispiel 4: form.json
{
"elements": [{
"type": "List",
"name": "Motors",
"caption": "Motoren",
"rowCount": 5,
"add": true,
"delete": true,
"columns": [{
"caption": "Name",
"name": "Name",
"width": "auto",
"add": "",
"save": true
}, {
"caption": "Position",
"name": "PositionID",
"width": "250px",
"add": 0,
"edit": { "type": "SelectVariable" }
}, {
"caption": "Wetterstation",
"name": "WeatherStationID",
"width": "250px",
"add": 0,
"edit": { "type": "SelectInstance" }
}, {
"name": "Sensor",
"visible": false,
"add": "",
"save": true
}],
"form": [{
"type": "ValidationTextBox",
"name": "Name",
"caption": "Name"
}, {
"type": "SelectVariable",
"name": "PositionID",
"caption": "Position"
}, {
"type": "Select",
"name": "WeatherStationID",
"caption": "Wetterstation",
"options": [],
"onChange": "SHD_UIWeatherStationChanged($id, $WeatherStationID);"
}, {
"type": "Select",
"name": "Sensor",
"caption": "Helligkeitssensor",
"options": [],
"visible": false
}]
}]
}
// Beispiel 4: module.php
<?php
declare(strict_types=1);
class Shading extends IPSModule
{
// GUID des Moduls der Wetterstation
private const WEATHER_STATION_MODULE_ID = '{5C9A1E3B-7D24-4F68-A0B1-2E3C4D5F6A7B}';
public function Create()
{
//Never delete this line!
parent::Create();
$this->RegisterPropertyString('Motors', '[]');
}
public function GetConfigurationForm()
{
$form = json_decode(file_get_contents(__DIR__ . '/form.json'), true);
// Das Formular der Zeilen hängt von der Wetterstation der Zeile ab und wird daher bei jedem Öffnen erzeugt
$form['elements'][0]['form'] = "return json_decode(SHD_UIMotorForm(\$id, \$Motors['WeatherStationID'] ?? 0), true);";
return json_encode($form);
}
// Wird vom PHP-Code in "form" aufgerufen und liefert die angepasste Vorlage
public function UIMotorForm(int $WeatherStationID): string
{
$form = json_decode(file_get_contents(__DIR__ . '/form.json'), true);
$motorForm = $form['elements'][0]['form'];
foreach ($motorForm as &$element) {
switch ($element['name'] ?? '') {
case 'WeatherStationID':
$element['options'] = $this->GetWeatherStationOptions();
break;
case 'Sensor':
$element['options'] = $this->GetSensorOptions($WeatherStationID);
$element['visible'] = $WeatherStationID !== 0;
break;
}
}
return json_encode($motorForm);
}
// Wird per onChange im Dialog aufgerufen und passt die Elemente des geöffneten Dialogs an
public function UIWeatherStationChanged(int $WeatherStationID)
{
$this->UpdateFormField('Sensor', 'options', json_encode($this->GetSensorOptions($WeatherStationID)));
$this->UpdateFormField('Sensor', 'visible', $WeatherStationID !== 0);
}
private function GetWeatherStationOptions(): array
{
$options = [['caption' => 'Keine', 'value' => 0]];
foreach (IPS_GetInstanceListByModuleID(self::WEATHER_STATION_MODULE_ID) as $instanceID) {
$options[] = ['caption' => IPS_GetName($instanceID), 'value' => $instanceID];
}
return $options;
}
private function GetSensorOptions(int $WeatherStationID): array
{
$options = [];
if (($WeatherStationID !== 0) && IPS_InstanceExists($WeatherStationID)) {
foreach (IPS_GetChildrenIDs($WeatherStationID) as $childID) {
if (IPS_VariableExists($childID)) {
$options[] = ['caption' => IPS_GetName($childID), 'value' => IPS_GetObject($childID)['ObjectIdent']];
}
}
}
return $options;
}
}
Weitere Beispiele zur Verwendung des form-Parameters können im Test-Repository gefunden werden.
Werte aus der Tabelle in PHP registrieren und auslesen
Wurde die Tabelle im Konfigurationsformular im Bereich elements definiert, kann die Tabelle durch die Funktion RegisterPropertyString registriert werden. Die Tabelle wird dann als JSON-codierter String gespeichert.
Die Funktion ReadPropertyString kann genutzt werden um den gespeicherten String auszulesen. In einem nächsten Schritt sollte die Funktion json_decode verwendet werden um den eingelesenen String in ein Array zu konvertieren.
Beispiel:
$arrString = $this->ReadPropertyString("devices");
$arr = json_decode($arrString);
Beispiel
//Einfache editierbare Liste von Instanzen und dazugehörigen Werten
//Die Liste enthält initial einen Eintrag
{
"type": "List",
"name": "Devices",
"caption": "Devices",
"rowCount": 5,
"add": true,
"delete": true,
"sort": {
"column": "Name",
"direction": "ascending"
},
"columns": [{
"caption": "InstanceID",
"name": "InstanceID",
"width": "75px",
"add": 0,
"edit": {
"type": "SelectInstance"
}
}, {
"caption": "Name",
"name": "Name",
"width": "auto",
"add": ""
}, {
"caption": "State",
"name": "State",
"width": "40px",
"add": "New!"
}, {
"caption": "Temperature",
"name": "Temperature",
"width": "75px",
"add": 20.0,
"edit": {
"type": "NumberSpinner",
"digits": 2
}
}],
"values": [{
"InstanceID": 12435,
"Name": "ABCD",
"State": "OK!",
"Temperature": 23.31,
"rowColor": "#ff0000" //rot
}]
}
Wird in der Beispieltabelle nun der Wert instanceID des ersten Eintrages auf 54321 und temperature auf 37.0 geändert und die Tabelle gespeichert, so werden die neuen Werte für instanceID und temperature als Modul-Eigenschaften persistent gespeichert. Da die weiteren Elemente, also name, state und die Farbe der Zeile rowColor, nicht editierbar sind, werden diese auch nicht gespeichert.
Wird die Tabelle nun erneut geladen, so werden zuerst die gespeicherten Werte für instanceID und temperature geladen. Die nicht-editierbaren Felder name und state werden dann mit den Werten aus values, also "ABCD" und "OK!" gefüllt. Die Farbe wird ebenfalls aus values geladen, wodurch die Zeile einen roten Hintergrund erhält.
Hätte man der Tabelle zusätzlich eine weitere Zeile hinzugefügt und die Werte instanceID und temperature auf 314 bzw. -5.3 gesetzt, so würden diese ebenfalls aus den Modul-Eigenschaften geladen werden. Da sich in values lediglich ein Element befindet, werden die nicht-editierbaren Felder entsprechend der Standardwerte aus add gefüllt. Das Feld name der zweiten Zeile würde leer bleiben und state würde auf "OK!" gesetzt werden. Da keine Farbe definiert ist, wäre der Hintergrund dieser Zeile transparent.
// Liste mit alternativer Sortierung
{
"type": "List",
"name": "sortList",
"rowCount": 5,
"add": false,
"columns": [
{
"caption": "Text",
"name": "Text",
"width": "auto",
"sortColumn": "Number"
},
{
"caption": "Number",
"name": "Number",
"width": "200px",
"visible": false
}
],
"values": [
{
"Text": "One",
"Number": "1"
},
{
"Text": "Two",
"Number": "2"
},
{
"Text": "Three",
"Number": "3"
}
]
}