Skip to content

docs-bug(MatInput): How to nest / wrap material form controls #23850

Open
@leon

Description

@leon

Documentation Feedback

I find myself getting stuck on this again and again, and I've been using angular and material since it's inception, so by now it should have stuck up there in the old noggin, but alas.

Today we have a basic tutorial on how to do a completely custom form field
https://material.angular.io/guide/creating-a-custom-form-field-control

but there is no tutorials examples of how to take an existing matInput mat-select or other form controls and wrap them into a component.
Usually we need to do this to DRY things up and not have to have the same error messages, options or reoccurring fields multiple times.

These are some tutorials / examples I would like to see

Custom component to wrap sub field names, validation and errors
I have an Address FormGroup which contains
street, zipcode, city
and a couple of mat-form-fields with labels, inputs, errors
I now want to wrap this into a <app-address-field formGroupName="customer.address" />

Custom mat-select with static list of values and validation
I have a Language select that is reused in multiple places
I now want to use it <app-lang-select formControlName="project.language" />

Custom input with some kind of dialog picker
A User picker, should display the user name when done, and an icon to the right much like a date picker.
but then in the dialog we have some custom logic to list all users, and the value that comes out of the picker should be the database id for the user.
<app-user-picker formControlName="client.salesPerson" />

The struggles

Since matInput already implements ControlValueAccessor it must be possible to just provide / delegate functionality down to that child, but how?

I have multiple implementations of the above, but all of them feel over complicated, or the dirty state isn't working because of something.

We need best practices for creating wrapped form controls and form groups :)

Please let me know if you need more context or examples, I have plenty

Activity

added
docsThis issue is related to documentation
needs triageThis issue needs to be triaged by the team
on Oct 28, 2021
added
good first issueThis issue is a good place to start for first time contributors to the project
help wantedThe team would appreciate a PR from the community to address this issue
P3An issue that is relevant to core functions, but does not impede progress. Important, but not urgent
and removed
needs triageThis issue needs to be triaged by the team
on Nov 7, 2021
yurakhomitsky

yurakhomitsky commented on Apr 20, 2022

@yurakhomitsky
Contributor

@leon I would like to take a look at some examples, just out of curiosity

mjamin

mjamin commented on Apr 28, 2022

@mjamin

Documentation should also provide an example how a wrapper component should be designed in a ChangeDetectionStrategy.OnPush context, since the error state is updated during ngDoCheck, which isn't called when a component that wraps mat-form-field uses OnPush and isn't marked for checking.

From what I understand, this solution only works if the input is either within the same view as the form, or if the change detection strategy is set to Default

pedroestabruxelles

pedroestabruxelles commented on Nov 22, 2022

@pedroestabruxelles

Since matInput already implements ControlValueAccessor it must be possible to just provide / delegate functionality down to that child, but how?

Found myself with the same problem last week.
What I did:
On the wrapper component add an @input() that receives the FormControl (I guess similar logic would apply for formgroup)
So the component would look like this:

<app-lang-select [control]="form.get('project.language')" />

And on the template
<mat-select [formControl]="control">

This approach made my life so much easier, i was already going crazy with the unnecessary complexity my component had before. But i agree that we need some sort of directive that would remove the need to do this way.

lionelgaillard

lionelgaillard commented on Jan 31, 2023

@lionelgaillard

I think I have the same problem:

Inside a <mat-form-field />, I have a custom component <app-companies-select /> which contains <mat-select matInput />.
but I still have the mat-form-field must contain a MatFormFieldControl error, because mat-form-field only checks for MatFormFieldControl in its direct children and not all descendants.

leon

leon commented on Feb 13, 2023

@leon
Author

Bumped into my own problem yet again...

I found this old talk which goes over the problem some what.
but I still feel a material specific guide would be a good idea.

https://youtu.be/CD_t3m2WMM8?t=1522

atakchidi

atakchidi commented on Apr 13, 2024

@atakchidi

This particular problem is the reason I can not recommend to use angular material for any large scale project.

Custom material control is ridiculously complex when you need to wrap well known element like input. Even if done right still dies not solve all the problems since you probably want another wrapper around whole form-field stuff.

I have examples where I implemented all of the mentioned solutions like custom control value accessor or just passing the control inside a wrapping component.

Nothing works as a complete solid experience that whole form in single place gives you.
With above solutions you can defeat the mat-errrors and relations between form-field and input.
But you will still loose relation with

so for instance submitting errored form will not highlight controls., because mat-form-fields are nit aware of dirtiness. You need some fancy custom error strategy or propagate the form state to each wrapping control yourself.

Controls and buttons are two main things require redesign to make material compatible in flexibility to any other design system solution out there in the market.
Clear guide is a bare minimum starting point here.

vborza

vborza commented on Apr 24, 2024

@vborza

@atakchidi may I ask you what UI component library would you recommend instead of Angular material? Do you have an experience with something more flexible?

leon

leon commented on Nov 26, 2024

@leon
Author

Bumped into this yet again, 3 years later. 😅

Could someone from the team please add a guide on how we can wrap a mat-select or mat-input and create a form control that works with form-fields.

I cannot be the only one who want to have custom form controls with reusable logic?

shhdharmen

shhdharmen commented on Jun 24, 2025

@shhdharmen

Not a perfect example, but I wrote something related to same issue couple of years back: https://blog.shhdharmen.me/creating-a-custom-form-field-control-group-using-angular-material

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3An issue that is relevant to core functions, but does not impede progress. Important, but not urgentarea: material/inputdocsThis issue is related to documentationgood first issueThis issue is a good place to start for first time contributors to the projecthelp wantedThe team would appreciate a PR from the community to address this issue

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @leon@mjamin@lionelgaillard@vborza@crisbeto

        Issue actions

          docs-bug(MatInput): How to nest / wrap material form controls · Issue #23850 · angular/components