Übergabe Index bei onEdit und onDelete in Listen

Moin liebes Symcon Team und Community,

Aktuell versuch ich mich an Live-Update der Konfigurationsform mittels der Funktion UpdateFormField

Hierzu habe ich einige Fragen:

  • Kann ich bei onEdit und onDelete in listen, den Index übergeben? Wie soll ich sonst erkennen welches Objekt verändert bzw. gelöscht wurde.
  • Wie kann ich erkennen das ein Object in einer Liste verschoben wurde.
  • Kann ich die Aktion „Änderung Verwerfen“ abfangen, um so gegen falls den Buffer zu leeren.
  • Kann ich irgendwie verhindern, das mir der Bereich „Änderung übernehmen/Verwerfen“ angezeigt wird, sobald ich das Formular mit der Funktion UpdateFormField ändern. Grund, wenn ich in Listen Informationspalten(die nicht durch den Nutzer angepasst werden können) ändere z.B. Aktuelle Helligkeit, usw. dann sorgt dieses dafür das der genannte Bereich angezeigt wird.

Über Hilfe, oder Ideen wär ich euch sehr dankbar.

Swen

Magst du vielleicht ausholen, wofür du die Informationen brauchst? Dann finden wir bestimmt gemeinsam eine passende Lösung für dich.

Da du bei der Aktualisierung einer Liste immer alle Felder per UpdateFormField aktualisierst (auch wenn die relevanten sicherlich gleich bleiben), wird dies entsprechend als Änderung erkannt. Den Verwerfen/Übernehmen-Bereich auszublenden ist aktuell nicht möglich und ich bin auch nicht wirklich ein Freund davon. Sind die Daten bei Aufruf der Konfigurationsform noch nicht vorhanden? Ansonsten könntest du diese cachen und per ReloadForm beim Neuladen mit in die Liste integrieren. Da die Konfiguration dann neu geladen wird, würde der Bereich für Änderungen dann wegbleiben.

erstmal danke für die Antwort.
Ich versuch es mal mit meinen Code zu erklären:

hab alles mal in eine Debug Repo hochgeladen
SymconModule/SymconJSLiveChart at Debug · Acer90/SymconModule (github.com)

public function ReloadFormDatasets($arr, $type){
        if(is_null($arr)) return;
        $formData = json_decode($this->GetBuffer("ConfigurationBuffer"), true);
        $axes = json_decode($this->GetBuffer("AxesBuffer"), true);
        $datasets = json_decode($this->GetBuffer("DatasetsBuffer"), true);

        $key = 0;
        foreach ($formData["elements"] as $keyNr => $element) {
            if (array_key_exists("name", $element) && $element["name"] === "Datasets") {
                $key = $keyNr;
                break;
            }
        }

        //In dem bereich liegt das Problem
        $id = ""; //<= hier breuchte ich den Index des auslösenden Datensatzes
        switch($type){
            case 0: //add
                $datasets[] = $arr;
                break;
            case 1: //change
                $datasets[$id] = $arr;
                break;
            case 2: //remove
                unset($datasets[$id]);
                break;
            case 3: //update
                //do nothing here
                break;
        }
        //ende Problemes

        //columns
        if (is_array($axes) && count($axes) > 0) {
            $colData = $formData["elements"][$key]["columns"];
            $colkey = array_search("Axes", array_column($colData, 'name'));

            $options_arr = array();
            $options_arr[] = array("value" => "", "caption" => "--Disable Dataset--");

            foreach ($axes as $item) {
                if(empty($item["Ident"])){
                    continue;
                }

                $caption = $item["Title"];
                if(empty($caption)) $caption = $item["Ident"];
                $options_arr[] = array("value" => $item["Ident"], "caption" => $caption);
            }

            $formData["elements"][$key]["columns"][$colkey]["add"] = $options_arr[0]["value"];
            $formData["elements"][$key]["columns"][$colkey]["edit"]["options"] = $options_arr;
        }

        //values
        foreach ($datasets as $row => $item) {
            $datasets[$row]["Dash"] = json_encode($datasets[$row]["Dash"]);
            if(!array_key_exists("Axes", $item)) {
                $datasets[$row]["rowColor"] = "#ff0000";
                continue;
            }

            $axesKey = array_search($item["Axes"], array_column($axes, 'Ident'));
            if(empty($item["Axes"]) || $item["Variable"] == 0 || $axesKey === false){
                $datasets[$row]["rowColor"] = "#ff0000";
            }
        }

        $this->UpdateFormField("Datasets", "columns", json_encode($formData["elements"][$key]["columns"]));
        $this->UpdateFormField("Datasets", "values", json_encode($datasets));
        $this->SetBuffer("ConfigurationBuffer", json_encode($formData));
        $this->SetBuffer("DatasetsBuffer", json_encode($datasets));
    }

form.json

{
            "type": "List",
            "name": "Datasets",
            "caption": "Datasets",
            "rowCount": 8,
            "add": true,
            "delete": true,
            "edit": true,
            "changeOrder": true,
            "onAdd": " SymconJSLiveChart_ReloadFormDatasets($id, $Datasets, 0);",
            "onEdit": " SymconJSLiveChart_ReloadFormDatasets($id, $Datasets, 1);",
            "columns": [
                {
                    "caption": "Type",
                    "name": "Type",
                    "width": "80px",
                    "add": "line",
                    "edit": {
                        "type": "Select",
                        "options": [
                            {
                                "caption": "Line",
                                "value": "line"
                            },
                            {
                                "caption": "Bar",
                                "value": "bar"
                            }
                        ]
                    }
                },
                {
                    "caption": "Variable",
                    "name": "Variable",
                    "width": "auto",
                    "requiredLogging": 1,
                    "add": 0,
                    "edit": {
                        "type": "SelectVariable"
                    }
                },
                {
                    "caption": "Axe",
                    "name": "Axes",
                    "width": "150px",
                    "add": "",
                    "edit": {
                        "type": "Select",
                        "options": [
                            {
                                "caption": "--Disable Dataset--",
                                "value": ""
                            }
                        ]
                    }
                },
                {
                    "caption": "Title",
                    "name": "Title",
                    "width": "300px",
                    "add": "",
                    "edit": {
                        "type": "ValidationTextBox"
                    }
                },
                {
                    "caption": "Offset",
                    "name": "Offset",
                    "width": "70px",
                    "add": 0,
                    "edit": {
                        "type": "NumberSpinner",
                        "digits": 0,
                        "minimum": 0
                    }
                },
                {
                    "caption": "Background Color",
                    "name": "BackgroundColor",
                    "width": "130px",
                    "add": 0,
                    "edit": {
                        "type": "SelectColor"
                    }
                },
                {
                    "caption": "Background Color Alpha",
                    "name": "BackgroundColor_Alpha",
                    "width": "50px",
                    "visible": false,
                    "add": 0.5,
                    "edit": {
                        "type": "HorizontalSlider",
                        "stepSize": 0.05,
                        "maximum": 1,
                        "minimum": 0
                    }
                },
                {
                    "caption": "Border Color",
                    "name": "BorderColor",
                    "width": "120px",
                    "add": 0,
                    "edit": {
                        "type": "SelectColor"
                    }
                },
                {
                    "caption": "Border Color Alpha",
                    "name": "BorderColor_Alpha",
                    "width": "50px",
                    "visible": false,
                    "add": 1.0,
                    "edit": {
                        "type": "HorizontalSlider",
                        "stepSize": 0.05,
                        "maximum": 1,
                        "minimum": 0
                    }
                },
                {
                    "caption": "Border Width",
                    "name": "BorderWidth",
                    "width": "120px",
                    "visible": false,
                    "add": 2,
                    "edit": {
                        "type": "NumberSpinner",
                        "digits": 0,
                        "minimum": 0
                    }
                },
                {
                    "caption": "Border Dash",
                    "name": "Dash",
                    "width": "100px",
                    "visible": false,
                    "add": "",
                    "edit": {
                        "type": "List",
                        "rowCount": 3,
                        "add": true,
                        "delete": true,
                        "sort": {
                            "column": "Order",
                            "direction": "ascending"
                        },
                        "columns": [
                            {
                                "caption": "Order",
                                "name": "Order",
                                "width": "150px",
                                "add": 0,
                                "edit": {
                                    "type": "NumberSpinner",
                                    "digits": 0,
                                    "minimum": 0
                                }
                            },
                            {
                                "caption": "Length",
                                "name": "Length",
                                "width": "auto",
                                "add": 0,
                                "edit": {
                                    "type": "NumberSpinner",
                                    "digits": 0,
                                    "minimum": 0,
                                    "suffix": "px"
                                }
                            }
                        ]
                    }
                },
                {
                    "caption": "HighRes",
                    "name": "HighRes",
                    "width": "150px",
                    "visible": false,
                    "add": 7,
                    "edit": {
                        "type": "Select",
                        "caption": "High-Res from",
                        "options": [
                            { "caption": "minute", "value": 7 },
                            { "caption": "hour", "value": 6 },
                            { "caption": "day", "value": 5 },
                            { "caption": "week", "value": 4 },
                            { "caption": "month", "value": 3 },
                            { "caption": "quarter", "value": 2 },
                            { "caption": "year", "value": 1 },
                            { "caption": "decade", "value": 0 }
                        ]
                    }
                },
                {
                    "caption": "Stack Group",
                    "name": "StackGroup",
                    "width": "100px",
                    "add": 0,
                    "edit": {
                        "type": "NumberSpinner",
                        "digits": 0,
                        "minimum": 0
                    }
                },
                {
                    "caption": "Monotone Interpolation",
                    "name": "MonotoneInterpolationMode",
                    "width": "100px",
                    "add": false,
                    "visible": false,
                    "edit": {
                        "type": "CheckBox"
                    }
                },
                {
                    "caption": "Tension",
                    "name": "Tension",
                    "width": "100px",
                    "add": 0.0,
                    "visible": false,
                    "edit": {
                        "type": "NumberSpinner",
                        "digits": 2,
                        "minimum": -1,
                        "maximum": 1
                    }
                },
                {
                    "caption": "Override Point Size",
                    "name": "PointRadius",
                    "width": "50px",
                    "visible": false,
                    "add": -1,
                    "edit": {
                        "type": "NumberSpinner",
                        "digits": 0,
                        "minimum": -1,
                        "suffix": "px"
                    }
                },
                {
                    "caption": "Override Point Style",
                    "name": "PointStyle",
                    "width": "50px",
                    "visible": false,
                    "add": "",
                    "edit": {
                        "type": "Select",
                        "options": [
                            { "caption": "-Use Default-", "value": "" },
                            { "caption": "circle", "value": "circle" },
                            { "caption": "cross", "value": "cross" },
                            { "caption": "crossRot", "value": "crossRot" },
                            { "caption": "dash", "value": "dash" },
                            { "caption": "line", "value": "line" },
                            { "caption": "rect", "value": "rect" },
                            { "caption": "rectRounded", "value": "rectRounded" },
                            { "caption": "rectRot", "value": "rectRot" },
                            { "caption": "star", "value": "star" },
                            { "caption": "triangle", "value": "triangle" }
                        ]
                    }
                },
                {
                    "caption": "Datalabels",
                    "name": "datalabels_enable",
                    "width": "100px",
                    "add": false,
                    "edit": {
                        "type": "CheckBox"
                    }
                },
                {
                    "caption": "Datalabels Override BackgroundColor",
                    "name": "datalabels_BackgroundColor",
                    "width": "130px",
                    "add": -1,
                    "visible": false,
                    "edit": {
                        "type": "SelectColor"
                    }
                },
                {
                    "caption": "Datalabels Override BackgroundColor Alpha",
                    "name": "datalabels_BackgroundColor_Alpha",
                    "width": "50px",
                    "visible": false,
                    "add": 0.5,
                    "edit": {
                        "type": "HorizontalSlider",
                        "stepSize": 0.05,
                        "maximum": 1,
                        "minimum": 0
                    }
                },
                {
                    "caption": "Datalabels Override BorderColor",
                    "name": "datalabels_BorderColor",
                    "width": "120px",
                    "add": -1,
                    "visible": false,
                    "edit": {
                        "type": "SelectColor"
                    }
                },
                {
                    "caption": "Datalabels Override BorderColor Alpha",
                    "name": "datalabels_BorderColor_Alpha",
                    "width": "50px",
                    "visible": false,
                    "add": 1.0,
                    "edit": {
                        "type": "HorizontalSlider",
                        "stepSize": 0.05,
                        "maximum": 1,
                        "minimum": 0
                    }
                },
                {
                    "caption": "Datalabels Override FontColor",
                    "name": "datalabels_FontColor",
                    "width": "120px",
                    "add": -1,
                    "visible": false,
                    "edit": {
                        "type": "SelectColor"
                    }
                },
                {
                    "caption": "Datalabels Override show Prefix",
                    "name": "datalabels_showPrefix",
                    "add": false,
                    "visible": false,
                    "edit": {
                        "type": "CheckBox"
                    }
                },
                {
                    "caption": "Datalabels Override show Suffix",
                    "name": "datalabels_showSuffix",
                    "add": false,
                    "visible": false,
                    "edit": {
                        "type": "CheckBox"
                    }
                }
            ]
        },

@Dr.Niels @paresy ich versuch es nochmal anders zu erklären.
Hier einmal ein Bild:

Achsen:
wenn eine Achse geändert, wird lese ich aus den Profil in der Achse hinterlegten Profil die werte Min/Max und Schrittgröße aus, sofern nichts für die Achse hinterlegt(überschreibt die werte aus dem Profil), oder eine Dynamische Skalierung gewählt wurde. Zusätzlich prüfe ich ob ein Ident und Profil gesetzt wurde wenn nicht wird die Achse Rot(Deaktiviert) und auch alle Datensätze die diese Achse verwenden sollen Rot(Deaktiviert) werden. Nach Prüfung ob die Einstellungen der Achse richtig sind wird der Kopf der Tabelle Datensätze (Hier Spalte Achse) geupdatet.
Diese Spalte ist ein Auswahlfeld und beinhaltet die oben angegebenen Achsen zur Auswahl.

Problem ändert sich der Ident, dann kann ich nicht mehr die alte Zeile ausfindig machen, da ich da ich dann nur den neuen Ident habe.

Datasets
Hier habe ich kein Ident, wenn ich also bei Änderung einen Datensatz Überprüfen möchte ob dieses richtig eingestellt ist müsste ich alle Datensätze erneut prüfen, das wäre auch grundsätzlich kein Problem, leider bekomme ich bei OnChange nur den geänderten Datensatz, nicht alle Datensätze.
Bei den Achsen hab ich das Problem gelöst, das er die angaben in einen Buffer schreibt, und die Achsen dann anhand des Ident aktualisiert.
Wenn bei den Funktionen OnChange und OnDelete ein Index übergeben würde könnte ich den buffer sauber updaten.

Zu dem Problem Änderung verwerfen, ich kann leider ein Änderung verwerfen nicht abfangen, somit stimmt mein Buffer(hier Achsen) nach den verwerfen nicht mehr. Hier wäre es gut dies mit einer Funktion abzufangen.

Soweit ich weiß schon von anderen gewünscht, wäre es gut wenn man auch das ändern der Reihenfolge per Drag and Drop abfangen könnte, (Hier alter Index => neue Index.

Problem Änderung übernehmen/verwerfen wenn ich mit updateform ein Label in eine Liste ändere.
Hier wäre es schön wenn es die Möglichkeit gibt das sofern nur lables(Infos) geändert werden, dann kein Einstellung übernehmen button angezeigt wird.

Kurzes Beispiel:

Spalte Current ist der Prozentuale wert aus Max wert und den aktuellen wert des Sensors.
Über einen Messagensink fange ich Änderungen des Sensors ab. die neuen Prozentualen werte aktualisiere ich dann im Konfigurationsformular.

durch diese Änderung kommt es Ausgabe der Schaltflächen Übernehmen/verwerfen, obwohl nur eine Infobox(Label) geändert wurde, die nicht durch den Nutzer gesetzt werden kann, geändert wurde.

Ich konnte es hoffentlich etwas besser aufgliedern, für eure Hilfe wäre ich euch sehr dankbar.
P.S. vielleicht hat @KaiS ja noch eine Idee.

Swen

Besten Dank für die ausführliche Erörterung!

Bei der Zuweisung der Achsen sehe ich mehrere Ansätze. Da es in den Einträgen scheinbar keinen eindeutigen Identifikator gibt, könntest du diesen ja einfach hinzufügen. Also eine unsichtbare Spalte „id“, welche du immer mit einer generierten GUID füllst oder dergleichen. Diese kannst du dann auch als Wertegrundlage für die Achsenauswahl nutzen. Für den Benutzer ist die ID unsichtbar, aber dann kannst du nach jeder Anpassung die Werte wieder neu darstellen und müsstest auch die Werte des Achsenfeldes in Datasets nicht aktualisieren sondern lediglich die Spalten. Da gäbe es auch noch andere Ansätze, dieser gefällt mir allerdings am besten.

Deine Annahme, dass du im onChange nur den geänderten Datensatz erhälst ist falsch. Du bekommst alle Einträge. Je nachdem, wie du zugreifst, erhälst du entweder die gesamte Liste oder nur die aktuell relevante Zeile. Schau mal hier: List — IP-Symcon :: Automatisierungssoftware

Was genau speicherst du jetzt im Buffer? Ich glaube, das ist nämlich gar nicht notwendig. Beim Laden der Form wäre mein Ansatz, dass du die Spalte entsprechend den Werten der Achsentabelle initialisieren und bei Änderungen dort das lokal aktualisieren, ganz ohne einen Buffer dazwischen. Der wirkt für mich hier nicht nach dem passenden Ansatz.

Die Anzeige von aktuellen Werten gehört schließlich eher in den „actions“-Bereich als in den „elements“-Bereich, in welchem es ja sowieso keine „aktualisierten Änderungen“ gibt, auch wenn ich verstehe, dass man das möglichwerweise alles an einer Stelle haben möchte. Da müssten wir mal schauen, was man da machen kann.

Per on-Funktion auf eine Änderung der Reihenfolge zu reagieren ist sicherlich nicht verkehrt, das notiere ich mir direkt. Da müsste man nur schauen, wie man die gesamte Verschiebung, also wie du schon geschrieben hast alter und neuer Index oder dergleichen, geeignet mit verpackt.

Daran hatte ich auch schon gedacht

Wenn ich selber eine id setzen würde breucht ich ja theoretisch nur den neuen index

Wenn ich das in den Action Bereich packe fehlt etwas die Übersicht, das soll ja den Nutzer bei Änderung des Wertes, oder max Wertes gleich die relation davon anzeigen

Danke das schau ich mir am Wochenende nochmal an, wenn ich fragen hab stell ich sie hier.

Im Buffer speichere ich immer den gesamten Values Inhalt der Liste(da ich der Annahme war das ich nur den geänderten Datensatz bekomme)

Danke für die Antwort

Swen