enhancement
major
minor
major
minor
major
#29535
TL Views table: a selection channel value that is not among the rows must not be cleared by the table
Problem
TableElement binds its selection channel two-way: the table writes the selected row to the channel, and a value written to the channel from elsewhere is applied as the table's selection (reapplySelection → control.selectRow(value)). When the value is not among the table's rows, the table ends up with no selected row and reports an empty selection through its selection listener, which writes null back to the channel - the table overrules a value it merely cannot display.
Two consequences observed:
- Several tables cannot share a selection channel. A board with three lanes (tables over the tickets of one project split by status category) with selection="selectedTicket" on all three: clicking a row in one lane makes the other two lanes, which do not contain that ticket, write null back, so no row stays selected and a single "Open" command over the shared channel is never enabled. The application had to give every lane its own channel and its own Open command.
- A created object is not selected. A create dialog writes the new object to the selection channel (<write-channel name="selectedProject"/>) before the table has refreshed its rows; the table, not yet containing the object, clears the channel, and the subsequent refresh selects nothing. The user has to click the row after creating it. (The reapplySelection after refresh is there for exactly this case but is defeated by the clearing.)
Lösung
Die Tabelle schreibt den Auswahlkanal nur noch in zwei Fällen:
- Benutzerinteraktion in der Tabelle: Auswählen oder Abwählen einer Zeile schreibt das Objekt (bzw. die Menge oder null) in den Kanal - wie bisher.
- Eine zuvor in dieser Tabelle ausgewählt angezeigte Zeile ist nach einer Aktualisierung der Zeilen verschwunden (Objekt gelöscht, durch geänderten Eingabekanal herausgefiltert, oder es erfüllt das Zeilenkriterium nicht mehr): die Tabelle setzt den Kanal auf null, damit ein benachbartes Formular kein Objekt mehr anzeigt, das die Tabelle nicht mehr enthält (Verhalten aus #29462, eingeschränkt auf Zeilen, die die Tabelle tatsächlich ausgewählt angezeigt hat).
Ein Kanalwert, der nicht unter den Zeilen der Tabelle ist, bedeutet dagegen nur "hier ist keine Zeile ausgewählt": die Tabelle zeigt keine Auswahl und lässt den Kanal unverändert. Damit können mehrere Tabellen einen Auswahlkanal teilen (die Tabelle, die das Objekt enthält, zeigt es ausgewählt, die anderen nichts), und ein frisch angelegtes Objekt, das ein Dialog vor der Aktualisierung der Zeilen in den Kanal schreibt, wird nach der Aktualisierung ausgewählt. Wandert ein Objekt durch eine Änderung von einer Tabelle in eine andere am selben Kanal, ist danach nichts ausgewählt (die Tabelle, die es angezeigt hat, leert den Kanal).
Technisch:
- Die Zwei-Wege-Bindung zwischen TableViewControl und ViewChannel liegt in der wiederverwendbaren Klasse com.top_logic.layout.view.model.TableSelectionBinding, die sowohl TableElement (nicht editierbare Tabelle) als auch RowSetTableControl (editierbare Tabelle in einem <form>) benutzen; die zuvor dort doppelt vorhandene Bindungslogik entfällt. Der Besitzer ruft nach TableViewControl.refreshData() rowsRefreshed() auf.
- TableViewControl benachrichtigt beliebig viele Selektions-Listener (addSelectionListener / removeSelectionListener), so dass die editierbare Tabelle neben der Kanalbindung ihren eigenen Listener für die Editierbarkeit der Zellen behalten kann.
- Test: TestTableSelectionBinding (zwei Tabellen über disjunkte Zeilenmengen an einem Kanal).
- Demo: tickets.view.xml in tl-demo-react (Navigationseintrag "Objektliste") zeigt zwei Tabellen (Tickets ohne / mit Kommentaren) an einem gemeinsamen Auswahlkanal.