passwordInvalid is a boolean that I would expect to be able to use to toggle the error state of the md-input.
I would expect to be able to do something like this:
<md-input-container [error]="passwordInvalid" >
<input name="password" tabindex="1" required mdInput
placeholder="Password" type="password" [(ngModel)]="user.password" value="{{user.password}}">
<md-error >Invalid login</md-error>
</md-input-container>
When passwordInvalid is true, the error state including showing the md-error would be toggled. When it goes back to false, it would return to a valid state.
Currently my ghetto work around:
<md-input-container [class.mat-input-invalid]="passwordInvalid" >
<input name="password" tabindex="1" required mdInput placeholder="Password" type="password" [(ngModel)]="user.password" value="{{user.password}}">
<md-error [class.mat-input-error]="passwordInvalid">Invalid login</md-error>
</md-input-container>
The md-error component/directive appears if they try to submit without entering anything because the field is required. When passwordInvalid is true, the styling works on the container but the md-error component/directive will not appear.
Is there something I'm missing from the docs?
You should be using async validator that accepts the passwordInvalid value and sets an error to the input. See the working plunker.
Click the passwordInvalid toggler to change its value and then start typing or hit the button to see the error.
my.validator.ts
import {Directive, OnInit, forwardRef, Input, OnChanges, SimpleChanges} from '@angular/core';
import {Validator, AbstractControl, NG_VALIDATORS, NG_ASYNC_VALIDATORS, ValidationErrors} from '@angular/forms';
import {BehaviorSubject} from "rxjs/BehaviorSubject";
@Directive({
selector: '[myValidator][ngModel]',
providers: [
{ provide: NG_ASYNC_VALIDATORS, useExisting: forwardRef(() => MyValidator), multi: true },
]
})
export class MyValidator implements OnInit, Validator, OnChanges {
@Input('myValidator')
public myValidator: boolean;
errors$: BehaviorSubject<ValidationErrors | null> = new BehaviorSubject<ValidationErrors | null>(null);
ngOnInit() {
this.errors$.next(this.myValidator);
}
ngOnChanges(changes: SimpleChanges) {
changes.myValidator && this.errors$.next(changes.myValidator.currentValue);
}
validate(c: AbstractControl) {
return this.errors$.asObservable().map(value => {
let obj = c.errors || {};
if (value) obj.myValidator = value;
else delete obj['myValidator'];
if (!Object.keys(obj).length) obj = null;
c.setErrors(obj);
console.log('obj', obj)
return obj;
});
}
}
Usage example:
<md-input-container>
<input name="password" tabindex="1" required mdInput
[myValidator]="passwordInvalid" #password="ngModel"
placeholder="Password" type="password" [(ngModel)]="user.password" value="{{user.password}}">
<md-error *ngIf="password.errors?.required" >Field is required</md-error>
<md-error *ngIf="password.errors?.myValidator">passwordInvalid</md-error>
{{ password.errors|json }}
</md-input-container>