Skip to content

Commit 55fb514

Browse files
committed
refactor: address feedback
1 parent bbca4cb commit 55fb514

File tree

8 files changed

+44
-58
lines changed

8 files changed

+44
-58
lines changed

src/lib/core/core.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,7 @@ export {
127127
MdErrorModule,
128128
MdError,
129129
ErrorStateMatcher,
130-
ErrorOptions,
131-
showOnDirtyErrorStateMatcher,
130+
ShowOnDirtyErrorStateMatcher,
132131
} from './error/index';
133132

134133
@NgModule({

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

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,18 @@
99
import {Injectable} from '@angular/core';
1010
import {FormGroupDirective, NgForm, NgControl} from '@angular/forms';
1111

12-
export type ErrorStateMatcher =
13-
(control: NgControl | null, form: FormGroupDirective | NgForm | null) => boolean;
14-
15-
/** Returns whether control is invalid and is either dirty or is a part of a submitted form. */
16-
export const showOnDirtyErrorStateMatcher: ErrorStateMatcher = (control, form) => {
17-
return control ? !!(control.invalid && (control.dirty || (form && form.submitted))) : false;
18-
};
12+
/** Error state matcher that matches when a control is invalid and dirty. */
13+
@Injectable()
14+
export class ShowOnDirtyErrorStateMatcher implements ErrorStateMatcher {
15+
match(control: NgControl | null, form: FormGroupDirective | NgForm | null): boolean {
16+
return control ? !!(control.invalid && (control.dirty || (form && form.submitted))) : false;
17+
}
18+
}
1919

20-
/**
21-
* Provider that defines how form controls behave with
22-
* regards to displaying error messages.
23-
*/
20+
/** Provider that defines how form controls behave with regards to displaying error messages. */
2421
@Injectable()
25-
export class ErrorOptions {
26-
isErrorState(control: NgControl | null, form: FormGroupDirective | NgForm | null): boolean {
22+
export class ErrorStateMatcher {
23+
match(control: NgControl | null, form: FormGroupDirective | NgForm | null): boolean {
2724
return control ? !!(control.invalid && (control.touched || (form && form.submitted))) : false;
2825
}
2926
}

src/lib/core/error/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@
99

1010
import {NgModule} from '@angular/core';
1111
import {MdError} from './error';
12-
import {ErrorOptions} from './error-options';
12+
import {ErrorStateMatcher} from './error-options';
1313

1414
@NgModule({
1515
declarations: [MdError],
1616
exports: [MdError],
17-
providers: [ErrorOptions],
17+
providers: [ErrorStateMatcher],
1818
})
1919
export class MdErrorModule {}
2020

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

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import {
2222
getMdInputContainerPlaceholderConflictError
2323
} from './input-container-errors';
2424
import {MD_PLACEHOLDER_GLOBAL_OPTIONS} from '../core/placeholder/placeholder-options';
25-
import {ErrorOptions, showOnDirtyErrorStateMatcher} from '../core/error/error-options';
25+
import {ErrorStateMatcher, ShowOnDirtyErrorStateMatcher} from '../core/error/error-options';
2626

2727
describe('MdInputContainer without forms', function () {
2828
beforeEach(async(() => {
@@ -895,11 +895,7 @@ describe('MdInputContainer with forms', () => {
895895
declarations: [
896896
MdInputContainerWithFormErrorMessages
897897
],
898-
providers: [
899-
{
900-
provide: ErrorOptions,
901-
useValue: { isErrorState: globalErrorStateMatcher } }
902-
]
898+
providers: [{ provide: ErrorStateMatcher, useValue: { match: globalErrorStateMatcher } }]
903899
});
904900

905901
let fixture = TestBed.createComponent(MdInputContainerWithFormErrorMessages);
@@ -926,12 +922,7 @@ describe('MdInputContainer with forms', () => {
926922
declarations: [
927923
MdInputContainerWithFormErrorMessages
928924
],
929-
providers: [
930-
{
931-
provide: ErrorOptions,
932-
useValue: { isErrorState: showOnDirtyErrorStateMatcher }
933-
}
934-
]
925+
providers: [{ provide: ErrorStateMatcher, useClass: ShowOnDirtyErrorStateMatcher }]
935926
});
936927

937928
let fixture = TestBed.createComponent(MdInputContainerWithFormErrorMessages);
@@ -1260,7 +1251,9 @@ class MdInputContainerWithCustomErrorStateMatcher {
12601251
});
12611252

12621253
errorState = false;
1263-
customErrorStateMatcher = () => this.errorState;
1254+
customErrorStateMatcher: ErrorStateMatcher = {
1255+
match: () => this.errorState
1256+
};
12641257
}
12651258

12661259
@Component({

src/lib/input/input-container.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ import {
4444
MD_PLACEHOLDER_GLOBAL_OPTIONS,
4545
PlaceholderOptions
4646
} from '../core/placeholder/placeholder-options';
47-
import {ErrorOptions, ErrorStateMatcher, MdError} from '../core/error/index';
47+
import {ErrorStateMatcher, MdError} from '../core/error/index';
4848
import {Subject} from 'rxjs/Subject';
4949
import {startWith} from '@angular/cdk/rxjs';
5050

@@ -188,7 +188,7 @@ export class MdInputDirective implements OnChanges, OnDestroy, DoCheck {
188188
get readonly() { return this._readonly; }
189189
set readonly(value: any) { this._readonly = coerceBooleanProperty(value); }
190190

191-
/** A function used to control when error messages are shown. */
191+
/** An object used to control when error messages are shown. */
192192
@Input() errorStateMatcher: ErrorStateMatcher;
193193

194194
/** The input element's value. */
@@ -222,7 +222,7 @@ export class MdInputDirective implements OnChanges, OnDestroy, DoCheck {
222222
constructor(private _elementRef: ElementRef,
223223
private _renderer: Renderer2,
224224
private _platform: Platform,
225-
private _errorOptions: ErrorOptions,
225+
private _globalErrorStateMatcher: ErrorStateMatcher,
226226
@Optional() @Self() public _ngControl: NgControl,
227227
@Optional() private _parentForm: NgForm,
228228
@Optional() private _parentFormGroup: FormGroupDirective) {
@@ -300,9 +300,8 @@ export class MdInputDirective implements OnChanges, OnDestroy, DoCheck {
300300
/** Re-evaluates the error state. This is only relevant with @angular/forms. */
301301
private _updateErrorState() {
302302
const oldState = this._isErrorState;
303-
const newState = this.errorStateMatcher ?
304-
this.errorStateMatcher(this._ngControl, this._parentFormGroup || this._parentForm) :
305-
this._errorOptions.isErrorState(this._ngControl, this._parentFormGroup || this._parentForm);
303+
const matcher = this.errorStateMatcher || this._globalErrorStateMatcher;
304+
const newState = matcher.match(this._ngControl, this._parentFormGroup || this._parentForm);
306305

307306
if (newState !== oldState) {
308307
this._isErrorState = newState;

src/lib/input/input.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -125,21 +125,23 @@ the error messages.
125125
```
126126

127127
```ts
128-
function myErrorStateMatcher(control: FormControl, form: FormGroupDirective | NgForm): boolean {
129-
// Error when invalid control is dirty, touched, or submitted
130-
const isSubmitted = form && form.submitted;
131-
return !!(control.invalid && (control.dirty || control.touched || isSubmitted)));
128+
class MyErrorStateMatcher implements ErrorStateMatcher {
129+
match(control: NgControl | null, form: FormGroupDirective | NgForm | null): boolean {
130+
// Error when invalid control is dirty, touched, or submitted
131+
const isSubmitted = form && form.submitted;
132+
return !!(control.invalid && (control.dirty || control.touched || isSubmitted)));
133+
}
132134
}
133135
```
134136

135137
A global error state matcher can be specified by setting the `ErrorOptions` provider. This applies
136-
to all inputs. For convenience, `showOnDirtyErrorStateMatcher` is available in order to globally
138+
to all inputs. For convenience, `ShowOnDirtyErrorStateMatcher` is available in order to globally
137139
cause input errors to show when the input is dirty and invalid.
138140

139141
```ts
140142
@NgModule({
141143
providers: [
142-
{provide: ErrorOptions, useValue: { isErrorState: showOnDirtyErrorStateMatcher }}
144+
{provide: ErrorOptions, useClass: ShowOnDirtyErrorStateMatcher}
143145
]
144146
})
145147
```

src/lib/select/select.spec.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import {Subject} from 'rxjs/Subject';
3131
import {ViewportRuler} from '../core/overlay/position/viewport-ruler';
3232
import {dispatchFakeEvent, dispatchKeyboardEvent, wrappedErrorMessage} from '@angular/cdk/testing';
3333
import {ScrollDispatcher} from '../core/overlay/scroll/scroll-dispatcher';
34-
import {ErrorOptions} from '../core/error/error-options';
34+
import {ErrorStateMatcher} from '../core/error/error-options';
3535
import {
3636
FloatPlaceholderType,
3737
MD_PLACEHOLDER_GLOBAL_OPTIONS
@@ -2689,24 +2689,24 @@ describe('MdSelect', () => {
26892689
expect(component.control.invalid).toBe(false);
26902690
expect(component.select._isErrorState()).toBe(false);
26912691

2692-
customErrorFixture.componentInstance.errorStateMatcher = matcher;
2692+
customErrorFixture.componentInstance.errorStateMatcher = { match: matcher };
26932693
customErrorFixture.detectChanges();
26942694

26952695
expect(component.select._isErrorState()).toBe(true);
26962696
expect(matcher).toHaveBeenCalled();
26972697
});
26982698

26992699
it('should be able to override the error matching behavior via the injection token', () => {
2700-
const errorOptions: ErrorOptions = {
2701-
isErrorState: jasmine.createSpy('error state matcher').and.returnValue(true)
2700+
const errorOptions: ErrorStateMatcher = {
2701+
match: jasmine.createSpy('error state matcher').and.returnValue(true)
27022702
};
27032703

27042704
fixture.destroy();
27052705

27062706
TestBed.resetTestingModule().configureTestingModule({
27072707
imports: [MdSelectModule, ReactiveFormsModule, FormsModule, NoopAnimationsModule],
27082708
declarations: [SelectInsideFormGroup],
2709-
providers: [{ provide: ErrorOptions, useValue: errorOptions }],
2709+
providers: [{ provide: ErrorStateMatcher, useValue: errorOptions }],
27102710
});
27112711

27122712
const errorFixture = TestBed.createComponent(SelectInsideFormGroup);
@@ -2715,7 +2715,7 @@ describe('MdSelect', () => {
27152715
errorFixture.detectChanges();
27162716

27172717
expect(component.select._isErrorState()).toBe(true);
2718-
expect(errorOptions.errorStateMatcher).toHaveBeenCalled();
2718+
expect(errorOptions.match).toHaveBeenCalled();
27192719
});
27202720
});
27212721

@@ -3272,6 +3272,6 @@ class CustomErrorBehaviorSelect {
32723272
{ value: 'steak-0', viewValue: 'Steak' },
32733273
{ value: 'pizza-1', viewValue: 'Pizza' },
32743274
];
3275-
errorStateMatcher = () => false;
3275+
errorStateMatcher: ErrorStateMatcher;
32763276
}
32773277

src/lib/select/select.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ import {
5757
// tslint:disable-next-line:no-unused-variable
5858
import {ScrollStrategy, RepositionScrollStrategy} from '../core/overlay/scroll';
5959
import {Platform} from '@angular/cdk/platform';
60-
import {ErrorStateMatcher, ErrorOptions} from '../core/error/error-options';
60+
import {ErrorStateMatcher} from '../core/error/error-options';
6161

6262
/**
6363
* The following style constants are necessary to save here in order
@@ -361,7 +361,7 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
361361
/** Input that can be used to specify the `aria-labelledby` attribute. */
362362
@Input('aria-labelledby') ariaLabelledby: string = '';
363363

364-
/** A function used to control when error messages are shown. */
364+
/** An object used to control when error messages are shown. */
365365
@Input() errorStateMatcher: ErrorStateMatcher;
366366

367367
/** Combined stream of all of the child options' change events. */
@@ -390,7 +390,7 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
390390
private _changeDetectorRef: ChangeDetectorRef,
391391
private _overlay: Overlay,
392392
private _platform: Platform,
393-
private _errorOptions: ErrorOptions,
393+
private _globalErrorStateMatcher: ErrorStateMatcher,
394394
renderer: Renderer2,
395395
elementRef: ElementRef,
396396
@Optional() private _dir: Directionality,
@@ -638,12 +638,8 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
638638

639639
/** Whether the select is in an error state. */
640640
_isErrorState(): boolean {
641-
if (this.errorStateMatcher) {
642-
return this.errorStateMatcher(this._control, this._parentFormGroup || this._parentForm);
643-
}
644-
645-
return this._errorOptions.isErrorState(this._control,
646-
this._parentFormGroup || this._parentForm);
641+
const matcher = this.errorStateMatcher || this._globalErrorStateMatcher;
642+
return matcher.match(this._control, this._parentFormGroup || this._parentForm);
647643
}
648644

649645
/**

0 commit comments

Comments
 (0)