5

How to make a Material custom form field control (like this one) to support form validation and display them with mat-error? I understand that the regular matInput directive uses ErrorStateMatcher (doc) but I don't understand how I can link it with a custom form field.

1

4 Answers 4

6

By looking at some existing component from Material2 (https://github.com/angular/components/blob/master/src/material/select/select.ts), I found a solution. I created a base class following this example

export const _MatSelectMixinBase:
CanDisableCtor &
HasTabIndexCtor &
CanDisableRippleCtor &
CanUpdateErrorStateCtor &
typeof MatSelectBase =
    mixinDisableRipple(mixinTabIndex(mixinDisabled(mixinErrorState(MatSelectBase))));

I had to copy from the Material repo some types like CanUpdateErrorStateCtor.

Then update my constructor to inject a ErrorStateMatcher and finally in ngDoCheck, do this:

ngDoCheck() {
   if (this.ngControl) {
      this.updateErrorState();
   }
}
Sign up to request clarification or add additional context in comments.

5 Comments

Spent the whole day solving this issue! Can't thank you enough!
@Rémi, the link leads to a 404 page. Also I cannot import MatSelectBase from anywhere. Maybe it's a private class now?
@TsvetanGanev it looks like the new link is this one github.com/angular/components/blob/master/src/material/select/….
MatSelectBase is a private class that you will have to copy. Search for _MatSelectMixinBase in the select.ts file.
Thanks. In the end I just copy-pasted Google's code into my own component. Dirty solution but it's the only one I found.
1

If you followed the official guide to create a custom material form field, and you have declared ngControl in constructor:

  constructor(
    ...,
    @Optional() @Self() public ngControl: NgControl) {
    ...

    if (this.ngControl != null) {
      this.ngControl.valueAccessor = this;
    }
  }

all you need is:

  get errorState(): boolean {
    return this.ngControl.invalid && this.ngControl.dirty;
  }

to get validation working.

Comments

0

you can check that from the FocusMonitor in the example ,it can be something like this:

  fm.monitor(elRef.nativeElement, true).subscribe(origin => {
    if (this.parts.status === 'INVALID') {
      this.errorState = true;
    }
    this.focused = !!origin;
    this.stateChanges.next();
  });

the idea is material provide errorState, you can see that from the component's type, so whenever you change it, it will reflect on the component, hope it's help!

Comments

0

The solution is correct! Reusing of mixinErrorState from material core is the best way to handle it. I recently released a detailed video about custom form field where also gave detailed explanation to error handling in custom form fields. It might be interesting for others who understands better by watching video https://youtu.be/AZsw2nRxkBk?t=825

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.