MD.OFFICE
FAL

2026-04-06

Matrix Formula Cells: External Reactivity & API Deduplication

Fixed issues where external formula fields referencing matrix formula row/column cells did not react to computed value changes, and eliminated redundant /evaluate API calls on interaction.

Decisions & Solutions

  • Pre-registered formula column controls in form-engine.service.ts so they exist at subscription time.
  • Maintained emitEvent: false on matrix formula computed setValue calls to prevent internal loops.
  • Consolidated notification: Called this.form.patchValue(this.form.value, { emitEvent: true }) on the nested FormGroup inside finalize() while _computingFormulas guard is true, bubbling one valueChanges up to external fields without triggering internal matrix recursion.
  • External field listener: Switched external formula fields to subscribe to the root form.valueChanges and use a getDependencySnapshot() snapshot comparison instead of individual subscriptions, ensuring they only react to meaningful changes.
  • Skipped null-dep evaluateFormula() on ngOnInit for formula fields since matrix-sourced deps start as null.

Matrix Structural Deletion Guards

Implemented structural safeguards to prevent the user from deleting a matrix row, column, or column group that is referenced inside an internal matrix formula or an external standard formula field.

Decisions & Solutions

  • Internal Guard (isRowUsedInMatrixFormulas, isColUsedInMatrixFormulas): Introduced positional-index regex scanning using negative lookahead (@Row.<N>(?!\d)) inside the right-panel to detect internal cross-references within the same matrix.
  • External Guard: Handled recursively via getFormulaKeysForMatrixStructure checking against areAnyKeysReferenced validating top-level dependent formulas targeting the specific matrix cell keys.
  • Interaction Hooking: Attached to removeMatrixRow, removeSimpleMatrixColumn, removeMatrixColumn, removeMatrixColumnGroup, onRowTypeChange, and onToggleFormulaColumn.
  • Visual Reversion: Added explicit UI visual reversion logic utilizing ChangeDetectorRef to snap DOM bindings (like dropdowns and toggles) out of stuck invalid states upon action denial.
  • Toasted alerts provide immediate contextual blocking notifications naming the specific dependency.

Matrix Bugfixes & Pipeline Resilience (Code Review)

Added critical safety guards to the formula evaluation pipeline based on code review recommendations.

Decisions & Solutions

  • API Error Handling (catchError): Appended catchError(err => of(null)) to evaluateSingleFormulaRow$ and evaluateFormulaColumn. This ensures that even if an API call fails (e.g. 500 status), the stream falls back gracefully allowing the pipeline chain to drop the lock flag (_computingFormulas), preventing the whole matrix from being stuck forever.
  • Subscription Cleanup (OnDestroy): Saved the primary observable execution stream explicitly into this.formulaSub and configured ngOnDestroy to unsubscribe it safely so memory leaks are prevented if the component unmounts mid-calculation.
  • Variable Refactor: Cleaned up the right-panel-static.component.ts helper getMatrixRowReferenceFields by re-typing regularRowNumber accurately as rowNumber to reflect its true positional function structure behind @Row.N.

Matrix Aggregate Calculation Optimization

Refactored the calculation of structural aggregates (Row sums, Column sums, and Row Count) to improve grid interaction performance.

Decisions & Solutions

  • Method Renaming: Renamed initializeSubscriptionForTotal to initializeMatrixSubscriptions and calculateTotal to calculateAggregates to better reflect their expanded scope.
  • Early Exit Performance Optimization: Implemented an "early exit" in calculateAggregates(). If includeRowAggregate, includeColumnAggregate, and includeRowCount are all disabled, the function returns immediately, skipping redundant summation loops over the grid.
  • Execution Ordering Fix: Hoisted the this.formulaSubject.next() trigger to the absolute top of the calculateAggregates flow. This ensures that custom cell formulas are still computed even if the structural aggregates (Sums/Counts) are disabled.

Iterative Matrix Formula Column Integration

Enabled support for Formula Columns within Iterative Matrix widgets, allowing dynamic tables to have per-row calculated columns.

Decisions & Solutions

  • UI Enablement: Removed the *ngIf restriction in the Right Panel that previously hid Formula Column configurations for iterative tables.
  • Dynamic Control Registration: Updated addRow() and iterative parsing logic in MatrixComponent to dynamically instantiate and attach formula column controls (e.g., matrixKey_rowKey_formulaColKey) for each new row.
  • Reactivity Pipeline: Updated the needsFormulaEvaluation check and core computation logic to permit formulaSubject.next() triggers and accurately map against iterativeRows.
  • Row Deletion & Shifting Fix: Hardened removeIterativeRow() to explicitly drop formula column FormControl instances upon deletion and shift surviving controls downward in the form model, preventing orphaned keys and memory leaks.
  • Builder Preview: Added iterative template placeholders to center-panel.component.html to visually represent the formula column during the design phase.