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.tsso they exist at subscription time. - Maintained
emitEvent: falseon matrix formula computedsetValuecalls to prevent internal loops. - Consolidated notification: Called
this.form.patchValue(this.form.value, { emitEvent: true })on the nested FormGroup insidefinalize()while_computingFormulasguard istrue, bubbling onevalueChangesup to external fields without triggering internal matrix recursion. - External field listener: Switched external formula fields to subscribe to the root
form.valueChangesand use agetDependencySnapshot()snapshot comparison instead of individual subscriptions, ensuring they only react to meaningful changes. - Skipped null-dep
evaluateFormula()onngOnInitfor 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
getFormulaKeysForMatrixStructurechecking againstareAnyKeysReferencedvalidating top-level dependent formulas targeting the specific matrix cell keys. - Interaction Hooking: Attached to
removeMatrixRow,removeSimpleMatrixColumn,removeMatrixColumn,removeMatrixColumnGroup,onRowTypeChange, andonToggleFormulaColumn. - Visual Reversion: Added explicit UI visual reversion logic utilizing
ChangeDetectorRefto 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): AppendedcatchError(err => of(null))toevaluateSingleFormulaRow$andevaluateFormulaColumn. 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 intothis.formulaSuband configuredngOnDestroyto unsubscribe it safely so memory leaks are prevented if the component unmounts mid-calculation. - Variable Refactor: Cleaned up the
right-panel-static.component.tshelpergetMatrixRowReferenceFieldsby re-typingregularRowNumberaccurately asrowNumberto 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
initializeSubscriptionForTotaltoinitializeMatrixSubscriptionsandcalculateTotaltocalculateAggregatesto better reflect their expanded scope. - Early Exit Performance Optimization: Implemented an "early exit" in
calculateAggregates(). IfincludeRowAggregate,includeColumnAggregate, andincludeRowCountare 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 thecalculateAggregatesflow. 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
*ngIfrestriction in the Right Panel that previously hid Formula Column configurations for iterative tables. - Dynamic Control Registration: Updated
addRow()and iterative parsing logic inMatrixComponentto dynamically instantiate and attach formula column controls (e.g.,matrixKey_rowKey_formulaColKey) for each new row. - Reactivity Pipeline: Updated the
needsFormulaEvaluationcheck and core computation logic to permitformulaSubject.next()triggers and accurately map againstiterativeRows. - Row Deletion & Shifting Fix: Hardened
removeIterativeRow()to explicitly drop formula columnFormControlinstances 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.htmlto visually represent the formula column during the design phase.