All notes

PR 10841 review-astra

The dynamic form builder becomes standalone. Its module and empty routing module are deleted.

Reviewed 25 September 2026112 files+501 / -402 lines

PR 10841 · Base 9a6dbec043 · Head 643b28fbfa

Should I merge it now? Yes.

I found no blocking regression at the reviewed commit.

The form fields retain their compiled template dependencies. Root providers cover the removed module's services, and the color picker still imports its provider module. Fresh TopFans and generated ajwhite QA client and server builds pass.

The largest measured saving is the post-price dialog. It needs about 86% less lazy JavaScript. This recommendation applies to 643b28fbfa. I did not independently repeat the signed-in browser flows or submit forms.

What changes

  • The module's 18 declared components become standalone. DynamicFormBuilderComponent imports each field its template renders.
  • 92 consumers replace DynamicFormBuilderModule with the components and directives they use.
  • DynamicFormBuilderModule and its routing module are deleted. The deleted route list was empty.

The first commit converts the fields while keeping the module. The second removes the module and updates consumers. My independent build checks cover the final head.

Code review

No form logic or template changes

An AST comparison found that all 110 modified files differ only in imports, standalone metadata or comments. The remaining two files delete the modules. Component methods, input and output declarations, validation logic, HTML and SCSS stay the same. The complete Git diff has 112 files, beyond the first 100 returned by the PR metadata query.

The five easily missed field components are present

FormTimePickerComponent, FormMultiSelectComponent, FormFileUploadInputComponent, FormFileUploadInputV2Component and ProfileImageUploadComponent were declared by the old module but never exported. They must be imported directly by the form builder after this migration.

All five appear in the new imports and in Angular's compiled template dependencies. The author describes an earlier attempt that missed them. That defect is absent from this head. See the form builder imports.

All 646 compiled components retain the dependencies they need

I compared fresh Angular output with saved output from PR 10840. Its source tree is identical to this PR's base. After resolving import aliases, 638 dependency lists match exactly. Eight lose only ngx-intl-tel-input's NativeElementInjectorDirective. No component dependency is added or lost otherwise.

That directive attaches a native element to a form control for the package's phone validator. None of the eight affected templates contains a phone input. MobileInputComponent keeps its phone module and its compiled dependencies. The comparison did not filter out any of the five field components above.

Removing the module does not leave missing providers

DynamicFormBuilderService and NgxImageCompressService already use root provisioning. The form service builds groups in local variables and keeps no per-form instance state. The image service holds its renderer and orientation constants. I found no dependency on a separate instance per former module importer.

PhoneMaskDirective and SsnMaskDirective remain registered in the shared root providers, and templates still import the directives where needed. The root also keeps the multiselect and circle-progress configuration. See the shared provider registrations.

Color picker coordination remains wired

ColorPickerModule provides ColorPickerService. FormColorPickerComponent imports that module, and the form builder imports FormColorPickerComponent. The installed Angular runtime collects providers through a standalone component's import tree when it creates that component's environment injector.

This preserves a provider path for pages and dynamically created dialogs that render the picker. The author also reports checking that opening a second picker closes the first. I verified the source wiring, but did not repeat that interaction. See the color picker imports.

Independent bundle measurements

Lazy entryBase bytesPR bytesBytes saved
Post-price dialog880,876123,375757,501
Edit preference4,322,4964,309,45813,038
Cover page3,166,0293,152,97213,057
Messages2,713,6332,700,61713,016
Wallet1,691,2391,678,19813,041
Dashboard5,097,3805,090,1267,254
Uncompressed JavaScript added after the initial load, including each entry's static dependencies. Entries share chunks, so these rows must not be added together. These are build sizes, not measured download times.

Initial JavaScript increases from 7,126,464 to 7,127,756 bytes, a gain of 1,292 bytes. The post-price dialog saves 757,501 bytes. Most of the larger routes save around 13 KB.

I calculated these values from the fresh QA build and the saved PR 10840 QA statistics. The saved base tree matches 9a6dbec043 exactly.

Checks run for this review

CheckResult
TopFans QA client and server buildPass. 42 warning groups, the same count as the base.
Generated ajwhite QA client and server buildPass. Generated from QA API data. 42 warning groups.
Angular compilationPass. All 646 component dependency lists compared.
Source comparisonPass. All 112 changed files checked.
Removed module referencesNo remaining references in application TypeScript.
Git whitespace checkPass.

Builds ran in an isolated checkout with a 10 GB Node heap limit and prerendering disabled. Generated white-label configuration and content were produced only in that checkout. The working frontend checkout was left untouched.

GitHub reported the PR mergeable with no status checks listed when reviewed. An empty check list is not a CI pass.

What this review does not prove

I did not independently run development builds, compare SSR responses, check hydration, open signed-in forms or submit uploads and payments. Compilation verifies the component wiring, but it cannot establish that every interaction succeeds.

The author reports QA and development builds for both commits, SSR comparisons over 145 URLs and signed-in white-label checks across 30 form pages. They also report checks of cover-page editors, post-type tabs, the time picker, file-upload-input-v2 and post-price dialogs. These are author-reported results.

The author did not save or submit forms. The multiselect and profile-image upload dialogs were not opened. Keep those two dialogs, form submission and upload completion in the release smoke tests. Their source wiring and compiled dependencies give me no specific reason to block this refactor.

Review references