Bug
When invoking markAsTouched for reactive form control whose value is invalid, corresponding custom material control (which implements ControlValueAccessor), should be highlighted and errors should be shown.
The control is highlighted, but no errors are shown. If the control get focused, then errors are shown.
StackBlitz starter: https://stackblitz.com/edit/angular-a2rrbx
Click the touch button. Then focus on the input.
Current behavior of custom control is not consistent with built-in material controls.
Angular 6.0.9, Angular/Material 6.4.0. Also present in previous versions, at least in 5.2.x. Tried in latest Chrome and IE 11.
This is not a bug, you can look the source of MatInput:
https://github.com/angular/material2/blob/master/src/lib/input/input.ts
Your custom form component has to extend what you get from mixinErrorState:
export class CustomComponentBase {
constructor(
public _defaultErrorStateMatcher: ErrorStateMatcher,
public _parentForm: NgForm,
public _parentFormGroup: FormGroupDirective,
public ngControl: NgControl
) { }
}
export const _CustomComponentMixinBase = mixinErrorState(CustomComponentBase);
As you implement MatFormFieldControl, the property errorState is mandatory but the mixinErrorState will implement this property for you :)
Then, call updateErrorState on ngDoCheck to display (or not) errors.
I guess the documentation could be better on this point ;)
Thanks!
I still don't understand though how to properly implement the mixin for my case - it throws injection error for NgForm.
Checks the source code of MatInput:
https://github.com/angular/material2/blob/master/src/lib/input/input.ts
export class CustomComponent extends CustomComponentBase {
...
constructor(
...,
@Optional() @Self() public ngControl: NgControl,
@Optional() _parentForm: NgForm,
@Optional() _parentFormGroup: FormGroupDirective,
_defaultErrorStateMatcher: ErrorStateMatcher
...,
) {
super(_defaultErrorStateMatcher, _parentForm, _parentFormGroup, ngControl);
// Setting the value accessor directly (instead of using
// the providers) to avoid running into a circular import.
if (this.ngControl != null) { this.ngControl.valueAccessor = this; }
}
...
Thank you! I the error was because I forgot to put Self on ngControl.
Checks the source code of MatInput:
https://github.com/angular/material2/blob/master/src/lib/input/input.tsexport class CustomComponent extends CustomComponentBase { ... constructor( ..., @Optional() @Self() public ngControl: NgControl, @Optional() _parentForm: NgForm, @Optional() _parentFormGroup: FormGroupDirective, _defaultErrorStateMatcher: ErrorStateMatcher ..., ) { super(_defaultErrorStateMatcher, _parentForm, _parentFormGroup, ngControl); // Setting the value accessor directly (instead of using // the providers) to avoid running into a circular import. if (this.ngControl != null) { this.ngControl.valueAccessor = this; } } ...
404 for the link
Thanks @rsaenen , this helped a lot. And you are right, the documentation could be better. It is not documented anywhere in the docs.
Also, if anyone is still looking the new source is at
https://github.com/angular/components/blob/master/src/material/input/input.ts
This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.
Read more about our automatic conversation locking policy.
_This action has been performed automatically by a bot._
Most helpful comment
404 for the link