angular / components

Component infrastructure and Material Design components for Angular
https://material.angular.io
MIT License
24.32k stars 6.72k forks source link

bug(MatFormField): Reactive Forms with FormGroup inside child component doesn't highlight when invalid #20341

Open eholman opened 4 years ago

eholman commented 4 years ago

Reproduction

Use StackBlitz to reproduce your issue: https://stackblitz.com/edit/angular-material-formgroup-nested

Steps to reproduce:

  1. Connect a form group to a child component (with custom input component) with validations configured
  2. Submit the form without value and the form is invalid

Expected Behavior

All the input fields that are invalid to get highlighted.

Actual Behavior

Components that are on the root group are highlighted

Environment

crisbeto commented 4 years ago

It looks like the problem is that the way we pick up the parent form of an input is by injecting NgForm (see here). You're using a formGroup on the form element which the NgForm directive's selector specifically excludes (the selector is form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]). This means that we have no good way of telling when a form is submitted, if it's using the reactive form directives. If you provide something yourself for the NgForm token that has a submitted property, it should work, although it's not ideal.

To resolve this on our end, we'd have to find another way of telling whether the parent form of a control is submitted, but from what I remember the last time I looked into it, there isn't anything else in @angular/forms. Worst case we can define a custom form directive for Material that only keeps track of the submitted state.

Totati commented 4 years ago

Hi, why are you using multiple FormGroup-s? You already use FormGroupName which is enought: https://stackblitz.com/edit/angular-material-formgroup-nested-qcygul?file=src/app/group-component/group-component.component.ts

eholman commented 4 years ago

Hi, why are you using multiple FormGroup-s? You already use FormGroupName which is enought: https://stackblitz.com/edit/angular-material-formgroup-nested-qcygul?file=src/app/group-component/group-component.component.ts

Many thanks for your fork! It's working great. Leaving out the FormGroup-s was part of the complete solution. Another part is the viewProvider that I don't understand (for the errors in hasError()). I'm not an Angular Expert but this viewProvider thing is very magical to me!

I cannot tell if the thing @crisbeto is talking about is needs to be solved or not...

mackelito commented 3 years ago

What if you don't want to have the FromGroup? My structure is that the formgroup is created in a parent component and then I just pass the control and name..

    <app-postal-code
      formControlName="postalCode"
      [ctrl]="deliveryAddress.controls.postalCode">
    </app-postal-code>

I just have access to the control and not the formgroup, this to get greater flexibility when reusing the form elements components

jscssphtml commented 1 year ago

I have the same Problem. I'm generating dynamic subforms presenting them in subcomonents which are injected via the ComponentPortal from the cdk. In these subcomponents i'm forced to use [formGroup] so that the subcomponent itsself is consistent.

Since the mixinErrorState is supported only with the direct parents the original form is not recognized. It's even not possible to "repair" this behavior by creating an own ErrorStateMatcher because the wrong parent is delivered in there.

As an interim solution i will try to implement an additional directive to the formGroup which "syncs" the submitted state.