Skip to content

feat(froms): add submit method to field state#66895

Open
mmalerba wants to merge 3 commits intoangular:mainfrom
mmalerba:sf/submit-2
Open

feat(froms): add submit method to field state#66895
mmalerba wants to merge 3 commits intoangular:mainfrom
mmalerba:sf/submit-2

Conversation

@mmalerba
Copy link
Contributor

@mmalerba mmalerba commented Feb 3, 2026

feat(froms): add submit method to field state

Changes the submit function from a separately imported function to a
method on the `FieldState

feat(forms): add field param to submit action and onInvalid

The action and onInvalid handlers now recevie two pieces of
information:

  1. The form that is being submitted
  2. The specific field that the submit was triggered on

@ngbot ngbot bot added this to the Backlog milestone Feb 3, 2026
@angular-robot angular-robot bot added the detected: feature PR contains a feature commit label Feb 3, 2026
Changes the `submit` function from a separately imported function to a
method on the `FieldState`
The `action` and `onInvalid` handlers now recevie two pieces of
information:
1. The form that is being submitted
2. The specific field that the submit was triggered on
this.parent?.updateValueAndValidity({sourceControl: this} as any),
);
this.fieldState = this.fieldTree();
this.fieldState = this.fieldTree() as FieldState<T>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What caused this cast to become necessary?

Copy link
Contributor Author

@mmalerba mmalerba Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm honestly not sure, here's what gemini told me:

The submit method introduced a circular dependency between FieldState and FieldTree that forced TypeScript to be stricter about structural compatibility.

Here is the breakdown:

  1. The New Cycle: The commit added submit(options: FormSubmitOptions<T>) to FieldState. FormSubmitOptions has a property action: (form: FieldTree<T>) => .... This creates a cycle: FieldStateFormSubmitOptionsFieldTreeFieldState.
  2. Structural Incompatibility: FieldTree<T> is a conditional type. If T is an AbstractControl, it returns CompatFieldState<T> (which is FieldState<ValueType>). However, SignalFormControl typed its fieldState property as FieldState<T> (which would be FieldState<AbstractControl>).
  3. Why it broke: Before the submit method, TypeScript likely didn't fully resolve the conditional type mismatch or treated the types as structurally compatible enough. The new submit method, with its function argument taking FieldTree<T>, made the types structurally distinct and incompatible (due to contravariance in the action callback), exposing the underlying issue that FieldState<AbstractControl> is not the same as FieldState<ValueType>.

If that is to be believed, it sounds like the types may not have been quite right to begin with and this just exposed the issue

@kirjs do you understand why I need this cast now?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

2 participants