enhancement
major
minor
defect
critical
major
minor
minor
#30205
React Table with Row Edit: A column based on a derived attribute is editable, but saving fails
Problem
In a <table row-edit="ALL">, an attribute column can be edited to a derived attribute (query attribute, <query> in the model). When saving, the error “Problem setting attribute value” appears.
Version: 8.0.0-alpha12, React View Layer (tl-layout-view/tl-layout-react).
Reproduction (Prime)
Maturity table in the status report (prime/project/status-report.view.xml), columns MaturityRating#suggestion and #sources defined as <column attribute="..."/>:
- Editing: Both cells are input fields.
- Change value, save: Error “Problem setting attribute value.”
Prime uses computed columnsfor this, which are read-only.
Expected Behavior
Derived attributes are read-only in row-edit tables, just as they are in forms.
The same applies to the dynamic visibility of an attribute (<dynamic-visibility>, TLDynamicVisibility): In the form, it calculates a field’s mode (hidden, read-only, disabled, editable, required) based on the object’s values and tracks changes to those values. In tables, this has been ignored until now. Furthermore, an attribute made mandatory by dynamic visibility (mode : mandatory) was marked as a required field in the form as well, but an empty value was not rejected upon saving.
Solution
- Static Mode: As in the form, the model determines whether a table cell for an attribute is editable: An attribute that is derived or annotated as non-editable is read-only in every attribute column, regardless of whether the column is declared (<column attribute="..."/>) or derived from the table. For new rows, the visibility at creation (create-visibility) applies. The parts of a non-editable composition are only displayed in the dialog.
- Dynamic Mode in Cells: The dynamic visibility of an attribute also applies in table cells. In an edited row, a cell’s mode is calculated for the object in that row and recalculated as soon as a value in the same row changes on which it depends: The cell is editable, read-only, an inactive input field, or marked as a required field. The “hidden” mode displays an empty cell—in both editable and read-only rows; the column remains, and other rows display their values. A hidden value is also excluded from sorting, filtering, searching, and exporting.
- Dynamic required fields are validated: If the dynamic visibility is set to `mandatory`, an empty value constitutes an error that is displayed in the field or cell and prevents saving—both in the form and in the table. Any mode other than `default` removes the requirement; `default` retains the attribute’s required status.
- Technical note: `AttributeModeTracker` is decoupled from the form (`AttributeChanges`: in the form, the field changes of the form; in the table, the value changes of the row in the `RowSetEditSession`). AttributeCellEditing uses the same mode calculation as the form field, and ColumnProviderService.attributeValue uses the same visibility rule for displayed cells. The mandatory check is performed in FormValidationModel (DynamicMandatoryConstraintCheck). The rules for each mode are located in one place (FormVisibility.isVisible(boolean), FormVisibility.isMandatory(boolean), DynamicVisibility).
Migration
The DynamicVisibility class is now located in the com.top_logic.model.annotate package ( tl-core module) instead of com.top_logic.layout.view.form. Java code that uses it must update the import statement:
import com.top_logic.model.annotate.DynamicVisibility;
Behavior Change: An attribute for which DynamicVisibility returns `mandatory` now prevents a React form or row-edit table from being saved if the value is empty. However, if DynamicVisibility returns `read-only`, `disabled`, `hidden`, or `editable`, an attribute declared as required in the model is no longer checked for required status.