Skip to content

Commit ab870d1

Browse files
committed
Address comments pt. 2
1 parent b0d69cc commit ab870d1

File tree

6 files changed

+40
-48
lines changed

6 files changed

+40
-48
lines changed

src/demo-app/input/input-demo.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ export class InputDemo {
4646
}
4747

4848
customErrorStateMatcher(c: NgControl): boolean {
49-
const isDirty = c.dirty;
49+
const hasInteraction = c.dirty || c.touched;
5050
const isInvalid = c.invalid;
5151

52-
return isDirty && isInvalid;
52+
return !!(hasInteraction && isInvalid);
5353
}
5454
}

src/lib/core/core.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,9 @@ export {
122122
export {
123123
ErrorStateMatcher,
124124
ErrorOptions,
125-
MD_ERROR_GLOBAL_OPTIONS
125+
MD_ERROR_GLOBAL_OPTIONS,
126+
defaultErrorStateMatcher,
127+
showOnDirtyErrorStateMatcher
126128
} from './error/error-options';
127129

128130
@NgModule({

src/lib/core/error/error-options.ts

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ import {InjectionToken} from '@angular/core';
1010
import {NgControl, FormGroupDirective, NgForm} from '@angular/forms';
1111

1212
/** Injection token that can be used to specify the global error options. */
13-
export const MD_ERROR_GLOBAL_OPTIONS =
14-
new InjectionToken<ErrorOptions>('md-error-global-options');
13+
export const MD_ERROR_GLOBAL_OPTIONS = new InjectionToken<ErrorOptions>('md-error-global-options');
1514

1615
export type ErrorStateMatcher =
1716
(control: NgControl, parentFormGroup: FormGroupDirective, parentForm: NgForm) => boolean;
@@ -20,26 +19,24 @@ export interface ErrorOptions {
2019
errorStateMatcher?: ErrorStateMatcher;
2120
}
2221

23-
export class DefaultErrorStateMatcher {
22+
export function defaultErrorStateMatcher(control: NgControl, formGroup: FormGroupDirective,
23+
form: NgForm): boolean {
2424

25-
errorStateMatcher(control: NgControl, formGroup: FormGroupDirective, form: NgForm): boolean {
26-
const isInvalid = control && control.invalid;
27-
const isTouched = control && control.touched;
28-
const isSubmitted = (formGroup && formGroup.submitted) ||
29-
(form && form.submitted);
25+
const isInvalid = control && control.invalid;
26+
const isTouched = control && control.touched;
27+
const isSubmitted = (formGroup && formGroup.submitted) ||
28+
(form && form.submitted);
3029

31-
return !!(isInvalid && (isTouched || isSubmitted));
32-
}
30+
return !!(isInvalid && (isTouched || isSubmitted));
3331
}
3432

35-
export class ShowOnDirtyErrorStateMatcher {
33+
export function showOnDirtyErrorStateMatcher(control: NgControl, formGroup: FormGroupDirective,
34+
form: NgForm): boolean {
3635

37-
errorStateMatcher(control: NgControl, formGroup: FormGroupDirective, form: NgForm): boolean {
38-
const isInvalid = control && control.invalid;
39-
const isDirty = control && control.dirty;
40-
const isSubmitted = (formGroup && formGroup.submitted) ||
41-
(form && form.submitted);
36+
const isInvalid = control && control.invalid;
37+
const isDirty = control && control.dirty;
38+
const isSubmitted = (formGroup && formGroup.submitted) ||
39+
(form && form.submitted);
4240

43-
return !!(isInvalid && (isDirty || isSubmitted));
44-
}
41+
return !!(isInvalid && (isDirty || isSubmitted));
4542
}

src/lib/input/input-container.spec.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import {
2424
getMdInputContainerPlaceholderConflictError
2525
} from './input-container-errors';
2626
import {MD_PLACEHOLDER_GLOBAL_OPTIONS} from '../core/placeholder/placeholder-options';
27-
import {MD_ERROR_GLOBAL_OPTIONS, ShowOnDirtyErrorStateMatcher} from '../core/error/error-options';
27+
import {MD_ERROR_GLOBAL_OPTIONS, showOnDirtyErrorStateMatcher} from '../core/error/error-options';
2828

2929
describe('MdInputContainer', function () {
3030
beforeEach(async(() => {
@@ -817,7 +817,7 @@ describe('MdInputContainer', function () {
817817
expect(containerEl.querySelectorAll('md-error').length).toBe(1, 'Expected an error message');
818818
});
819819

820-
it('should display an error message when using ShowOnDirtyErrorStateMatcher', async(() => {
820+
it('should display an error message when using showOnDirtyErrorStateMatcher', async(() => {
821821
TestBed.resetTestingModule();
822822
TestBed.configureTestingModule({
823823
imports: [
@@ -830,7 +830,10 @@ describe('MdInputContainer', function () {
830830
MdInputContainerWithFormErrorMessages
831831
],
832832
providers: [
833-
{ provide: MD_ERROR_GLOBAL_OPTIONS, useClass: ShowOnDirtyErrorStateMatcher }
833+
{
834+
provide: MD_ERROR_GLOBAL_OPTIONS,
835+
useValue: { errorStateMatcher: showOnDirtyErrorStateMatcher }
836+
}
834837
]
835838
});
836839

@@ -1136,8 +1139,8 @@ class MdInputContainerWithFormErrorMessages {
11361139
<form #form="ngForm" novalidate>
11371140
<md-input-container>
11381141
<input mdInput
1139-
[formControl]="formControl"
1140-
[errorStateMatcher]="customErrorStateMatcher.bind(this)">
1142+
[formControl]="formControl"
1143+
[errorStateMatcher]="customErrorStateMatcher.bind(this)">
11411144
<md-hint>Please type something</md-hint>
11421145
<md-error>This field is required</md-error>
11431146
</md-input-container>

src/lib/input/input-container.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ import {
4343
MD_PLACEHOLDER_GLOBAL_OPTIONS
4444
} from '../core/placeholder/placeholder-options';
4545
import {
46-
DefaultErrorStateMatcher,
46+
defaultErrorStateMatcher,
4747
ErrorStateMatcher,
4848
ErrorOptions,
4949
MD_ERROR_GLOBAL_OPTIONS
@@ -241,8 +241,7 @@ export class MdInputDirective {
241241
this.id = this.id;
242242

243243
this._errorOptions = errorOptions ? errorOptions : {};
244-
this.errorStateMatcher = this._errorOptions.errorStateMatcher
245-
|| new DefaultErrorStateMatcher().errorStateMatcher;
244+
this.errorStateMatcher = this._errorOptions.errorStateMatcher || defaultErrorStateMatcher;
246245
}
247246

248247
/** Focuses the input element. */

src/lib/input/input.md

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -110,11 +110,12 @@ warn color.
110110

111111
### Custom Error Matcher
112112

113-
By default, error messages are shown when the control is invalid and the user has interacted with
114-
(touched) the element or the parent form has been submitted. If you wish to customize this
115-
behavior (e.g. to show the error as soon as the invalid control is dirty), you can use the
116-
`errorStateMatcher` property of the `mdInput`. To use this property, create a function in
117-
your component class that returns a boolean. A result of `true` will display the error messages.
113+
By default, error messages are shown when the control is invalid and either the user has interacted with
114+
(touched) the element or the parent form has been submitted. If you wish to override this
115+
behavior (e.g. to show the error as soon as the invalid control is dirty or when a parent form group
116+
is invalid), you can use the `errorStateMatcher` property of the `mdInput`. To use this property,
117+
create a function in your component class that returns a boolean. A result of `true` will display
118+
the error messages.
118119

119120
```html
120121
<md-input-container>
@@ -125,17 +126,18 @@ your component class that returns a boolean. A result of `true` will display the
125126

126127
```ts
127128
function myErrorStateMatcher(control: NgControl, parentFg: FormGroupDirective, parentForm: NgForm): boolean {
128-
return control.invalid && control.dirty;
129+
return !!(control.invalid && control.dirty);
129130
}
130131
```
131132

132133
A global error state matcher can be specified by setting the `MD_ERROR_GLOBAL_OPTIONS` provider. This applies
133-
to all inputs.
134+
to all inputs. For convenience, `showOnDirtyErrorStateMatcher` is available in order to globally cause
135+
input errors to show when the input is dirty and invalid.
134136

135137
```ts
136138
@NgModule({
137139
providers: [
138-
{provide: MD_ERROR_GLOBAL_OPTIONS, useValue: { errorStateMatcher: myErrorStateMatcher }}
140+
{provide: MD_ERROR_GLOBAL_OPTIONS, useValue: { errorStateMatcher: showOnDirtyErrorStateMatcher }}
139141
]
140142
})
141143
```
@@ -145,14 +147,3 @@ Here are the available global options:
145147
| Name | Type | Description |
146148
| ----------------- | -------- | ----------- |
147149
| errorStateMatcher | Function | Returns a boolean specifying if the error should be shown |
148-
149-
150-
If you just wish to make all inputs behave the same as the default, but show errors when
151-
dirty instead of touched, you can use the `ShowOnDirtyErrorStateMatcher` implementation.
152-
153-
```ts
154-
@NgModule({
155-
providers: [
156-
{ provide: MD_ERROR_GLOBAL_OPTIONS, useClass: ShowOnDirtyErrorStateMatcher }
157-
]
158-
})

0 commit comments

Comments
 (0)