MD.OFFICE
FAL

2026-04-01

Matrix Widget: Row Count — Renderer

Completed the renderer-side of the Matrix Row Count feature. The builder side (Phase 1) was already merged; today's work makes the row count display live and correctly in the actual form filled by end users.

What we built

matrix.component.ts

  • Registered a single FormControl per table using the key ${matrixKey}_row_count:
    • Static tables: registered in ensureNormalMatrixControls(), initialized to config.rows.length.
    • Iterative tables: registered in ensureIterativeRowControls(), guarded by iterativeRows.length === 1 (same guard pattern already used for column sum controls), initialized to 0.
  • Extended calculateTotal() with a row-count block: for iterative tables count = iterativeRows.length (automatically reactive via the existing valueChanges subscription); for static tables count = config.rows?.length. Equality check prevents infinite loops.
  • Added getRowCountControl() public helper — mirrors the getSumControlForRow/Col pattern so the template can access the control directly.

matrix.component.html (renderer)

  • Added <tr *ngIf="config.includeRowCount"> summary row before the column aggregate row in both iterative and static table blocks.
  • Count input appears in the last data cell only (not first):
    • Simple columns: let last = last on *ngFor, show input only when last.
    • Grouped columns: let lastGroup = last on group loop + let lastCol = last on column loop, show input only when lastGroup && lastCol. Ensures one count per table regardless of group count.
  • Fixed actions-column filler in the iterative Row Count row: removed bg-gray-100 to match un-highlighted actions column style.
  • Added <!-- Column Aggregate Row (iterative) --> comment for readability.

Additional fixes

center-panel.component.html (builder)

  • Added border border-gray-300 to all row-aggregate filler cells (*ngIf="item.includeRowAggregate") that were missing borders inside:
    • Iterative Row Count row (grouped + simple branches)
    • Iterative Column Aggregate row (grouped + simple branches)
    • Static Row Count row grouped branch
    • Static Column Aggregate row grouped branch
  • Fixes visual table grid gaps where filler cells for the row-aggregate column had no border, causing a visual break in the table layout.

Matrix Widget: Row Count — Formula Reference Support (Phase 3)

Allowed the Row Count cell (${matrixKey}_row_count) to be selected in the @ mention dropdown of the formula builder and resolved by the formula evaluator, just like column sum cells.

Decisions & Solutions

  • No renderer changes needed: The ${matrixKey}_row_count FormControl was already registered in the live FormGroup (Phase 2), so formula evaluation works automatically.
  • Label format: Set to ${labelPath}.${el.rowCountLabel || 'Count'}.
  • Iterative table refactor: Changed an early return to a conditional block in updateFormulaFieldSuggestions() so the iterative branch can push the row count entry when includeRowCount is true.
  • Guard in onToggleRowCount(): Added a formula-reference guard to block disabling Row Count if referenced, showing an error toast.
  • checkRowCount option: Added to getFormulaKeysForMatrixStructure() in dynaform.service.ts to push ${matrixKey}_row_count into the keys array for reference checking.
  • Updated right-panel-static.component.ts (iterative, static simple, and static grouped branches) and dynaform.service.ts accordingly.

Matrix Widget: Row Count — Validation Rule Fix

Fixed an issue where validation rules referencing @Table.Count (e.g., @Expense.Count < 5) always showed an error, regardless of the actual count because the _row_count control was not pre-registered when validators were attached.

Decisions & Solutions

  • Pre-register _row_count: Updated FormEngineService.addMatrixControls to pre-register the _row_count FormControl before attachFormulaValidators runs. The matrix component's own registration is safely guarded against conflicts.
  • Iterative tables: Pre-registered column sum controls and _row_count in the early return block.
  • Static tables: Added addControl('${matrixKey}_row_count', rows.length) after column sum registration for both simple and grouped modes in form-engine.service.ts.