enhancement
major
minor
major
minor
major
#29610
TL Views: a table on an inactive tab shows stale cell values after the displayed objects changed, until its rows are refreshed
Problem
In the issue tracker tl-dev the project home is a <tab-bar> (Board, Tickets, Roadmap, …), each tab holding <table observed-types="tl.dev:Ticket"> elements over the project's tickets. The tab bar keeps the content of a tab that was active once.
Steps:
- Open the project home, activate the Tickets tab (its table shows a ticket with status New).
- Switch to the Board tab and change that ticket's status - by dropping its row on another lane (#29545), or by opening its page and running Accept, then returning through the breadcrumb.
- Switch back to the Tickets tab.
Observed: the ticket's status cell still reads New (and Closed stays after a reopen). The row set is right, the cells are stale until something refreshes the rows (a filter, a sort, a reload). The Board lanes on the active tab follow the change immediately, so the observation itself works; the table on the inactive tab either does not receive the change while its control is not displayed, or receives it and does not re-render the cells of the rows it keeps.
Reproduced with both a lane drop and the ticket page's Accept command, so it is independent of the command that changes the object.
Solution
A table whose control is kept while its tab is inactive re-renders the rows whose objects changed when it is displayed again (or applies the change events it collected while hidden), the same way its rows follow the change while it is displayed. A test in tl-layout-view: two tabs with tables over the same objects, a change while the second tab is inactive, the second tab's cells after activation.
Lösung
Cause. The tab bar keeps the control of a tab that was active once and detaches it while another tab is shown; the <table>'s RowSourceObserver removes its model listeners on detach, so a change while the tab is hidden reaches nobody. When the tab is shown again, the observer re-reads the rows but delivers them only where the row list differs from the one at hand. The rows are the same objects, so nothing is delivered, the table control does not rebuild its cells, and the row states rendered before the change are sent to the client again.
The same gap exists for the displays that observe the object on a channel through ChannelObjectObserver without recomputing on attach: <text input="…"> (label and color of the object), <switch>, <progress>.
Fix in the shared observers, not per display.
- RowSourceObserver: an observation that resumes after a suspension (attach after a detach) delivers the re-read elements unconditionally - the objects may have changed unseen. The first attach stays silent while the elements are the ones the display was built from. This covers <table>, <object-list>, <calendar> and the row-set table of a form.
- ChannelObjectObserver: an observer whose holder re-reads the channels itself (the Runnable callback) runs the callback once when it resumes. The form receiving the ModelChangeEvent (the scroll link hiding a deleted target) is unchanged.
A change while the tab is hidden is still not observed; the display catches up where it resumes, at the cost of one rebuild per return to a tab.
Tests in tl-layout-view: resuming with unchanged elements delivers them, the first attach stays silent (TestRowSourceObserver, TestChannelObjectObserver); a detached text control catches up when displayed again (TestTextElementObservation); the scenario of this ticket in TestTabbedTableObservation: the tab bar control of a window with two tables over the same committed objects, wired the way <table> wires them, an edit committed while the first tab is hidden, and the first tab's cell showing the stored value as the client receives it once the tab is displayed again (plus: the hidden tab keeps its cells until then, the displayed tab follows at once). Verified in the browser in tl-demo-react, view Attribute: a value edited on the Selector + Form tab shows in the Table tab's cell right after switching back.