enhancement
major
minor
defect
critical
major
minor
minor
#30198
React-Views: Baumtabelle ({{{<tree-table>}}}) ohne Zeilenbearbeitung ({{{row-edit}}}) – kein Ersatz für das klassische Tree-Grid
Problem
Im neuen View-Layer gibt es keine Baumtabelle, deren Zeilen sich in einem Formular bearbeiten lassen.
- <table row-edit="ALL|SELECTED"> (RowSetTableControl) bearbeitet nur flache Zeilenmengen.
- <tree-table> hat laut Doku „no rows, no group-by and no row-edit“.
- edit-in-place="true" auf der <tree-table> ist kein Ersatz:
- Jeder Wert wird sofort in einer eigenen Transaktion geschrieben, ohne gemeinsames Speichern/Abbrechen.
- Attributspalten werden nicht in place bearbeitet; nötig wären berechnete Spalten mit eigenem <update>.
- Das klassische Tree-Grid (GridComponent mit TreeGridBuilder) kann genau das: Baum, zeilenweise Bearbeitung, je Zeile nur die Felder des Zeilentyps. Im React-View-Layer lässt es sich aber nicht einbetten.
Version: 8.0.0-alpha12, Modul tl-layout-react (TreeTableElement, RowSetTableControl).
Anwendungsfall
Statusübersicht im Projekt (Neubau VW PRIME):
- Baum aus Projekt → Teilprojekt → Unterteilprojekt → Arbeitspaket.
- Je Zeile der laufende Statusbericht mit Ampeln, Fortschritt und Bemerkung zur Massenpflege.
- Die Alt-Anwendung zeigt das als Tree-Grid.
- Workaround: flache <table row-edit="ALL"> in Baumreihenfolge mit einer PSP-Spalte für die Gliederung. Ein- und Ausklappen sowie die Einrückung fehlen dabei.
Erwartetes Verhalten (Vorschlag)
<tree-table row-edit="ALL|SELECTED"> innerhalb eines <form>, analog zur flachen Tabelle:
- Die Zellen der bearbeitbaren Zeilen zeigen die Eingabe der Attributspalte (AttributeCellEditing). Das Attribut wird am Zeilentyp aufgelöst, so dass Zeilen ohne das Attribut leer und nicht bearbeitbar bleiben.
- Die Änderungen werden gepuffert und mit dem Speichern des Formulars gemeinsam geschrieben.
- Während der Bearbeitung bleibt der Baum eingefroren (kein Neuaufbau, Aufklappzustand bleibt).
- Wünschenswert: Hinzufügen und Entfernen von Kindzeilen über die Composition des Elternknotens.
Auswirkung
Massenpflege über hierarchische Daten ist ein Kernmuster migrierter TL-7-Anwendungen (Tree-Grid). Ohne Baum-Row-Edit bleiben nur flache Ersatzlösungen.
Lösung
<tree-table row-edit="ALL|SELECTED"> innerhalb eines <form> bearbeitet die Zeilen des Baums wie die flache Row-Edit-Tabelle: {{{#!xml <form input="editAnchor">
<tree-table row-edit="ALL" on-remove="DELETE" selection="selected"
types="demo.tickets:Project,demo.tickets:Item"
root="$project" children="$node.get(demo.tickets:Item#children)">
<inputs><input channel="project"/></inputs>
<add-child create-type="demo.tickets:Item"
insert="$parent.add(demo.tickets:Item#children, $child)"/>
<columns>...</columns>
</tree-table>
</form> }}}
- Gepufferte Bearbeitung: Die Zellen bearbeitbarer Zeilen zeigen die Eingabe ihrer Spalte; das Attribut wird am Typ der jeweiligen Zeile aufgelöst. Alle Änderungen werden mit dem Speichern des Formulars gemeinsam geschrieben, Abbrechen verwirft sie. Mit row-edit="SELECTED" ist genau die ausgewählte Zeile bearbeitbar.
- Zeilen kommen beim Aufklappen hinzu: Eine Zeile wird erst in die Bearbeitung aufgenommen, wenn sie angezeigt wird (ihr Elternknoten aufgeklappt ist). Das Aufklappen macht das Formular nicht geändert. Damit funktioniert die Bearbeitung auch für große oder unbeschränkte Bäume (canExpandAll="false").
- Baum während der Bearbeitung: Der Baum wird nicht aus Modelländerungen anderer Stellen neu aufgebaut, sondern folgt den Eingaben im Formular: die children-Funktion wird über den Puffern des Formulars ausgewertet, so dass hinzugefügte und entfernte Zeilen sofort erscheinen bzw. verschwinden. Neu berechnet werden nur die Kinderlisten, die einen geänderten Wert gelesen haben. Der Aufklappzustand und die Auswahl bleiben über den Wechsel zwischen Anzeige- und Bearbeitungsmodus erhalten. Nach Speichern oder Abbrechen folgt der Baum wieder dem Modell.
- Kindzeilen hinzufügen mit <add-child create-type="…" insert="…"/>: create-type berechnet aus dem Elternobjekt ($parent: die ausgewählte Zeile, ohne Auswahl das Wurzelobjekt des Baums) den Typ des neuen Objekts – eine abstrakte Klasse bietet ihre konkreten Spezialisierungen in einem Menü an, kein Ergebnis bietet für diesen Elternknoten kein Hinzufügen an. insert fügt das neue, noch nicht gespeicherte Objekt ($child) in den Puffer des Elternobjekts ein, typischerweise in eine Komposition; gespeichert wird erst mit dem Formular. Die Elternzeile wird aufgeklappt, die neue Zeile ausgewählt und bearbeitbar. parent-as / child-as benennen die Variablen um.
- Zeilen entfernen mit on-remove="DELETE": Die Zeile verschwindet sofort und wird beim Speichern gelöscht, Abbrechen holt sie zurück. Mit dem Objekt werden die Teile seiner Kompositionen gelöscht; Zeilen, die nur über eine einfache Referenz unter der gelöschten Zeile hingen, verschwinden aus der Anzeige, werden aber nicht gelöscht. on-remove="UNLINK" ist an einer Baumtabelle ein Konfigurationsfehler.
- Einschränkung: Eine Rückwärtsreferenz (kind="backwards") wird aus den gespeicherten Objekten beantwortet. Ein Kind, das nur über eine Rückwärtsreferenz des Elternknotens gefunden wird, erscheint daher erst nach dem Speichern; Kinder werden über eine Vorwärtsreferenz (Komposition) des Elternobjekts eingefügt.
- row-edit außerhalb eines <form> sowie zusammen mit edit-in-place, <drag> oder <drop> ist wie bei der flachen Tabelle ein Konfigurationsfehler.
- Behoben nebenbei: Eine Attributspalte zeigt in einer Zeile, deren Typ das Attribut nicht hat, keine Zelle mehr. Bisher erschien z.B. für ein Wahrheitswert-Attribut eine leere Checkbox bzw. im Bearbeitungsmodus ein deaktiviertes Eingabefeld (betrifft alle Tabellen mit Zeilen verschiedener Typen).
Demo in tl-demo-react: Demos → Baum-Raster (Projektbereiche → Meilensteine / Liefergegenstände → Tickets), einmal mit row-edit="ALL" (Meilensteine hinzufügen, Zeilen löschen), einmal mit row-edit="SELECTED" (Liefergegenstände eines gewählten Typs hinzufügen).
Technisch: RowSetTableControl ordnet seine Zeilen über ein RowArrangement an (flach: ListRowArrangement, Baum: TreeRowArrangement auf dem RowTree, den auch die lesende Baumtabelle nutzt); neue Zeilen entstehen über RowCreation (ChildRowCreation für <add-child>). RowSetEditSession#adoptRows nimmt gespeicherte Zeilen während einer laufenden Bearbeitung als ursprüngliche Zeilen auf. row-edit und on-remove sind jetzt Eigenschaften aller Tabellenelemente (AbstractTableElement.Config). Doku: Artikel view-layer/tree-tables, Abschnitt „Editing rows“.