Components: FR: Create a component that adds validation and error messages to any form control

Created on 19 Oct 2017  路  42Comments  路  Source: angular/components

Bug, feature request, or proposal:

feature request

What is the current behavior?

can't use checkbox and radio inside form-field.

What is the use-case or motivation for changing an existing behavior?

form-field provide a common way to display field description (hints) and message errors and I would like to have the same behavior for checkbox and radio.

P5 materiaform-field feature

Most helpful comment

Very Ugly temporary hack that hurts

Wrap a mat-form-filed with always floatPlaceholder and add a matInput that it's display:none.

<mat-form-field floatPlaceholder="always" class="mat-form-field--no-underline">
  <!-- the matInput with display:none makes the magic. It's ugly, I've warned you -->
  <input matInput placeholder="Input" style="display: none" >
  <mat-radio-group>
    <mat-radio-button value="1">Option 1</mat-radio-button>
    <mat-radio-button value="2">Option 2</mat-radio-button>
  </mat-radio-group>
</mat-form-field>

Now, we just need a workaround to remove the mat-input-underline.

.mat-form-field--no-underline .mat-input-underline {
  background-color: transparent;
}

Result

screen shot 2017-11-08 at 1 33 06 pm

PS: Make sure you share your formControlName between mat-radio-group/mat-checkbox and the ugly [matInput] {display:none}

Eq: http://plnkr.co/edit/NrihcY?p=preview

All 42 comments

<mat-form-field class="example-medium-width">
        <mat-select matInput name="cars" [(ngModel)]="vehicles.cars" placeholder="Cars" multiple #field_cars="ngModel">
            <mat-option *ngFor="let car of cars" [value]="car">
                {{ car }}
            </mat-option>
        </mat-select>

    </mat-form-field>

The Select implementation here is pretty standard for template-driven forms and it works like a charm. Thanks to the "multiple" here, one can select multiple values and then cars are submitted nicely which are all part of one single variable. Easy to cycle thru, easy to paint. No maps to deal with, No code to manage indexes, none of that. You get your cars as an array! Just cannot get any better than that.

I hope that when the checkbox implementation is done, it would be done the same way so it will be as easy and as consolidated as the select implementation in my example. I should be able to group checkboxes under one group and handle that hassles free just like the current select box

How about add mat-slider to the list?

Very Ugly temporary hack that hurts

Wrap a mat-form-filed with always floatPlaceholder and add a matInput that it's display:none.

<mat-form-field floatPlaceholder="always" class="mat-form-field--no-underline">
  <!-- the matInput with display:none makes the magic. It's ugly, I've warned you -->
  <input matInput placeholder="Input" style="display: none" >
  <mat-radio-group>
    <mat-radio-button value="1">Option 1</mat-radio-button>
    <mat-radio-button value="2">Option 2</mat-radio-button>
  </mat-radio-group>
</mat-form-field>

Now, we just need a workaround to remove the mat-input-underline.

.mat-form-field--no-underline .mat-input-underline {
  background-color: transparent;
}

Result

screen shot 2017-11-08 at 1 33 06 pm

PS: Make sure you share your formControlName between mat-radio-group/mat-checkbox and the ugly [matInput] {display:none}

Eq: http://plnkr.co/edit/NrihcY?p=preview

I was learning about the mat-selection-list and I've realized that it comes with a Label as [mat-subheader].

It turned out it works for checkboxes and radio group as well.

Try something like so:

RadioGroup

<mat-list>
    <h3 mat-subheader>Label for RadioGroup</h3>
    <mat-radio-group class="example-radio-group" [(ngModel)]="favoriteSeason">
    <mat-radio-button class="example-radio-button" *ngFor="let season of seasons" [value]="season">
      {{season}}
    </mat-radio-button>
  </mat-radio-group>
</mat-list>

Checkbox Group

<mat-selection-list #groceries>
  <h3 mat-subheader>Groceries</h3>

  <mat-list-option checkboxPosition="before" value="bananas">Bananas</mat-list-option>
  <mat-list-option checkboxPosition="before" selected value="oranges">Oranges</mat-list-option>
  <mat-list-option checkboxPosition="before" value="apples">Apples</mat-list-option>
  <mat-list-option checkboxPosition="before" value="strawberries">Strawberries</mat-list-option>
</mat-selection-list>

Eq: https://plnkr.co/edit/k73FSy?p=preview

@tinayuangao I don't think we want to have radio buttons or checkboxes inside of form fields. form fields are only intended for things that have the floating label & underline style that input and select share. But error messages on radio & checkboxes is a reasonable request

Perhaps what is missing is a label that could be used as a field description for fields, such as radio-group, checkbox list, slider and some others

I guess we can always use Material Typography such as .mat-h4 or just wrap the <h4> in a .mat-typography:

<section class="mat-typography">
  <h4>Label for RadioGroup</h4>
  <mat-radio-group class="example-radio-group" [(ngModel)]="favoriteSeason">
    <mat-radio-button class="example-radio-button" *ngFor="let season of seasons" [value]="season">
      {{season}}
    </mat-radio-button>
  </mat-radio-group>
</section>

Also mat-selection-list should be wrapable in mat-form-field too, for a common style of validation messages, hints, etc.

I've just created a new issue (https://github.com/angular/material2/issues/11333) presenting the expected behavior in another way: I just asked to support validation errors on such inputs.

Just wondering how this hasn't been implemented.
This must be a must for a lot of people. (Pun intended)

I have the same problem. For me I need the error message, when it is required and nothing was checked, inside a mat-readio-group. And the required indicator * is missing. It is set dynamically. Sure, I can add it again with ngIf and a new tag but it radio buttons and checkboxes are form fields, since the beginning. Input, textarea, checkbox, radio buttons and smth more.

all controls should work inside form-field.
now I have to do extra work to make all the fields look consistently (label hint ...)
and I need to remember if use mat-raido-group or checkbox then I need use my-form-field instead of mat-form-field that is very annoying

Still no solution with this problem?
Tried today to put checkbox of form (reactive approach) and had to add custom styles to make it fit vertically right because impossible to put checkbox inside mat-form-field. Also mat-error is dispayed not correctly (probably cuz it is not inside mat-form-field afterall).

wrapping them in form-field would do the job, that's what I did for ngx-formly integration: https://formly.dev/ui/material

wrapping them in form-field would do the job, that's what I did for ngx-formly integration: https://formly-js.github.io/ngx-formly/ui/material

Sure, but you provide your component as MatFormFieldControl and implement MatFormFieldControl<T>.

import { MatFormField, MatFormFieldControl } from '@angular/material';

@Component({
  // (...)
  providers: [{ provide: MatFormFieldControl, useExisting: FormlyWrapperFormField }],
})
export class FormlyWrapperFormField implements MatFormFieldControl<any> {
  // (...)
}

Since Angular Material version 7 there is a guide for doing this with custom controls:
Creating a custom form field control

We should be able to add this feature in the same way for the Angular Material radio buttons and checkboxes.

We should also look into how the Angular Material select component implements this.

Any update on a fix for this? This has been a recurring issue for many for quite a long time now...

I was having troubles hiding the underline. Eventually worked using ::ng-deep

::ng-deep .mat-form-field--no-underline .mat-form-field-underline { background-color: transparent !important; }

I'd like to add button toggle groups to this request, they basically behave the same as radio groups with different styling.

Can we know what is the point behind not supporting checkbox and radio in mat-form-field?

Having issue tho with Radio Buttons. Set them up as required and after user submit the form without checking the radio buttons, he doesn't get any error message. Very weird thing ...

Here is the solution we are using:
https://stackblitz.com/edit/material-if-errors?file=app%2Fif-error.ts

It has the advantage that it can be used to show errors for any control. Since most error matchers just check touched, dirty, and valid, you could get away with passing it a FormGroup cast to a FormControl to show errors at the group level.

Still looking for an update to this. Any progress?

Came searching for an update on this multiple times.

(I'm going through the highest voted issues today an commenting on their status)

We currently don't have any active plans to work on this, primarily because we don't really see how it fits in with the Material Design spec. What we call "form-field" maps to text fields. We used the term "form-field" since the spec clearly shows the treatment being used for selects/dropdowns as well. The spec doesn't, though, show any other type of interaction with this treatment; our interpretation here has been that directly supporting it wouldn't be in the spirit of the Material Design spec.

That said, there is an API for using _any_ control inside of MatFormField. You can create a custom directive like myCustomFormControl that extends MatFormFieldControl to integrate with the form-field (example in the docs) and then apply this custom directive to any component you need.

:( bootstrap supports checkboxes and radio buttons inside forms, they are so common everywhere. What would I do when my client asks please add the checkboxes, radio buttons for Yes/No, I have seen them elsewhere. I would be like u know what we are elite we are material.

P.S. - hope he doesn't know about custom directives :P

OK , so we need open an issue at Material Design spec's github then.

As a developer, I DO NOT like the attitude of you don't need what you want to do, but then I am not paying for this so I just suck it up and move one. But yes it would be very nice to add the check box inside the form fields, because, well check boxes are on forms.

I'd like to have some sort of checkbox-group that can be put inside mat-form-field. For example, we want to create a field where we want the user to check all the categories that they have interest in. I don't want to use selection list because if I have a lot of options, it takes up a lot of space. I think it is very reasonable to have radio-group & checkbox-group inside a form field so it can have label, hint, & error validation.

@jelbourn Hi Jeremy, here is the Material design description of checkboxes:

https://material.io/components/selection-controls/#checkboxes

How do you interpret the spec to exclude non-textual form controls? The other Material "selection controls" are radio buttons and switches. Other non-textual controls described include sliders and various buttons.

Further, in the description of "Form Fields", the very 1st example is a check box!?!
https://material.io/develop/web/components/input-controls/form-fields/

Can you share a link to where in the spec it says, "What we call 'form-field' maps to text fields"?

My instinct is that you are, perhaps, interpreting the spec too literally in this case. I.e. you are taking anything not expressly permitted as denied. In this case, anything not expressly denied, that fits into common use and aligns with other existing web standards, should be _encouraged_.

@CharlieReitzel what @jelbourn is saying is that the thing we (Angular Material) call <mat-form-field> corresponds to what the Material Design spec calls a "Text field" https://material.io/components/text-fields/ (yes, the differing terminology is confusing). We currently don't have any single component that corresponds to a generic form control wrapper, we have <mat-checkbox> for checkboxes, <mat-radio> for radio buttons, and <mat-form-field> for text inputs and selects.

@mmalerba @jelbourn I understand what Jeremy said. I am asking for more information about the rationale behind that decision. Specifically, I am asking, where in the Material Design and Angular Component specifications that limitation is stated? Can you please share the relevant spec(s)?

Again, my feeling is that it isn't being read quite right. That association seems altogether too narrow to be truly useful to developers. I have worked around it for the moment. But the results are not satisfactory. As others have said, most <mat-form-field> features are not specific to text fields, e.g. displaying validation errors, highlighting controls with errors, label display, etc.

There is nowhere in the spec, as far as I know, that discusses validation and error messages for checkboxes, radio buttons, etc. I think some kind of generic form control container is a reasonable thing to ask for, though without any mention of it in the spec, it's not going to be a high priority for the team.

I've renamed this issue to avoid any confusion about mat-form-field, what this issue is asking for would be implemented as a separate new component

@jelbourn said,

We currently don't have any active plans to work on this, primarily because we don't really see how it fits in with the Material Design spec.

All I'm asking is which spec (link please)? And where in it are you seeing that you shouldn't support both text fields and selection controls under <mat-form-field>? There is clearly a lot of support in favor of this feature request. So, at a minimum, it will help us all understand your reasoning.

I'm seeing this, in Introduction to Material Design, Components:

Material Components are interactive building blocks for creating a user interface, and include a built-in states system to communicate focus, selection, activation, error, hover, press, drag, and disabled states.

A bit later, as part of a list of components,

Input: Entering information or selections, using components such as text fields, chips, and selection controls.

"Selection controls" refer to check box, radio button and switch components, collectively. So I'm seeing fairly direct support in (what looks like) the Material Design "spec" for what the OP and many others are asking. So, please, can you tell us? What are we all missing?

<mat-form-field> is a detail of our implementation of the spec, so the spec says nothing about it. It is completely separate from the concept of "selection controls" in the spec. I really don't know how to explain this any better, I feel like I'm just repeating myself.

Separately, the idea of validation and errors that applies universally to any form control sounds like a good idea to me, but it is not something that the spec covers. I can't link you to where it doesn't cover it because... it's not in the spec. Nowhere does it show what an error message for a checkbox would look like. I'd prefer to see the spec add some guidance on this rather than just making up our own UI and having it turn out to be completely off spec later on

@mmalerba Are you talking about this spec: Angular Material Components?
Or this one: Material Design "Design"?
Or something else?

I'm referring to the second one; the first one is not a spec, it's the documentation site for this project

please add this, or rename mat-form-field to something else and make a new component to wrap all controls

I'm late to the party on this: I think it's apparent after 2.5 years there's no interest from the component group on hooking these inputs up to mat-form-field, but unfortunately for me our UX requirements aren't 100% on board with the material specification I guess.

Before I jump on the pain train tomorrow and create my own: has anyone already created a basic MatFormFieldControl directive that can be applied to the non-'text' fields (specifically MatSelectionList)?

Really all I need is for the styling (error handling) to function, and I'd rather not add hidden inputs everywhere.

Really all I need is for the styling (error handling) function, and I'd rather not add hidden inputs everywhere.

There are several workarounds upthread. If all you are worried about is showing errors, the ifError directive I posted should work. I notice our current implementation is different from that stackblitz, so I updated it.

https://stackblitz.com/edit/material-if-errors?file=app%2Fif-error.ts

Any update on it. I use the alternative methods
<div class="col-lg-6"> <div class="full-width"> <mat-checkbox formControlName="is_active">Utilisateur active</mat-checkbox> </div> </div>
Form control Name work on this case

Still a problem in 2021 - I think the general attitude is that "we know whats best for you" and so the workarounds continue.

We were able to make this work (for us at least) by adding in a custom label and relevant form errors below the checkbox.

<div class="flex-column p-b-large">
  <label for="exampleCheck">
    Checkbox example label:
    <span class="required" aria-hidden="true"></span>
  </label>

  <mat-checkbox id="exampleCheck" formControlName="checked">
    I Accept
  </mat-checkbox>

  <mat-error *ngIf="formErrors('checked')">
    You must accept to continue.
  </mat-error>
</div>
Was this page helpful?
0 / 5 - 0 ratings

Related issues

savaryt picture savaryt  路  3Comments

vanor89 picture vanor89  路  3Comments

MurhafSousli picture MurhafSousli  路  3Comments

julianobrasil picture julianobrasil  路  3Comments

theunreal picture theunreal  路  3Comments