Skip to content

Commit 10e6502

Browse files
crisbetojelbourn
authored andcommitted
fix(form-field): always use native input value to determine whether control is empty (#13307)
Currently we use the input value accessor to figure out whether an input has a value. This doesn't handle the case with `matDatepicker` where we have a custom accessor whose model value may not change, even though the value in the input has changed. These changes switch to always using the value from the input element. Fixes #13305.
1 parent 845388c commit 10e6502

File tree

2 files changed

+51
-6
lines changed

2 files changed

+51
-6
lines changed

src/lib/input/input.spec.ts

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,15 @@ import {
55
wrappedErrorMessage,
66
MockNgZone,
77
} from '@angular/cdk/testing';
8-
import {ChangeDetectionStrategy, Component, ViewChild, Type, Provider, NgZone} from '@angular/core';
8+
import {
9+
ChangeDetectionStrategy,
10+
Component,
11+
ViewChild,
12+
Type,
13+
Provider,
14+
NgZone,
15+
Directive,
16+
} from '@angular/core';
917
import {ComponentFixture, fakeAsync, flush, TestBed} from '@angular/core/testing';
1018
import {
1119
FormControl,
@@ -35,8 +43,7 @@ import {By} from '@angular/platform-browser';
3543
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
3644
import {MatStepperModule} from '@angular/material/stepper';
3745
import {MatTabsModule} from '@angular/material/tabs';
38-
import {MatInputModule} from './index';
39-
import {MatInput} from './input';
46+
import {MatInputModule, MatInput, MAT_INPUT_VALUE_ACCESSOR} from './index';
4047
import {MatTextareaAutosize} from './autosize';
4148

4249
describe('MatInput without forms', () => {
@@ -889,6 +896,20 @@ describe('MatInput without forms', () => {
889896
expect(formField.classList).not.toContain('mat-form-field-type-mat-native-select');
890897
});
891898

899+
it('should use the native input value when determining whether ' +
900+
'the element is empty with a custom accessor', fakeAsync(() => {
901+
let fixture = createComponent(MatInputWithCustomAccessor, [], [], [CustomMatInputAccessor]);
902+
fixture.detectChanges();
903+
let label = fixture.debugElement.query(By.css('label')).nativeElement;
904+
905+
expect(label.classList).toContain('mat-form-field-empty');
906+
907+
fixture.nativeElement.querySelector('input').value = 'abc';
908+
fixture.detectChanges();
909+
910+
expect(label.classList).not.toContain('mat-form-field-empty');
911+
}));
912+
892913
});
893914

894915
describe('MatInput with forms', () => {
@@ -1368,7 +1389,8 @@ describe('MatInput with textarea autosize', () => {
13681389

13691390
function createComponent<T>(component: Type<T>,
13701391
providers: Provider[] = [],
1371-
imports: any[] = []): ComponentFixture<T> {
1392+
imports: any[] = [],
1393+
declarations: any[] = []): ComponentFixture<T> {
13721394
TestBed.configureTestingModule({
13731395
imports: [
13741396
FormsModule,
@@ -1379,7 +1401,7 @@ function createComponent<T>(component: Type<T>,
13791401
ReactiveFormsModule,
13801402
...imports
13811403
],
1382-
declarations: [component],
1404+
declarations: [component, ...declarations],
13831405
providers,
13841406
}).compileComponents();
13851407

@@ -1876,3 +1898,26 @@ class MatInputSelectWithLabel {}
18761898
</mat-form-field>`
18771899
})
18781900
class MatInputSelectWithInnerHtml {}
1901+
1902+
@Component({
1903+
template: `
1904+
<mat-form-field floatLabel="never">
1905+
<input matInput customInputAccessor placeholder="Placeholder">
1906+
</mat-form-field>`
1907+
})
1908+
class MatInputWithCustomAccessor {}
1909+
1910+
1911+
/** Custom component that never has a value. Used for testing the `MAT_INPUT_VALUE_ACCESSOR`. */
1912+
@Directive({
1913+
selector: 'input[customInputAccessor]',
1914+
providers: [{
1915+
provide: MAT_INPUT_VALUE_ACCESSOR,
1916+
useExisting: CustomMatInputAccessor
1917+
}]
1918+
})
1919+
class CustomMatInputAccessor {
1920+
get value() { return this._value; }
1921+
set value(_value: any) {}
1922+
private _value = null;
1923+
}

src/lib/input/input.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ export class MatInput extends _MatInputMixinBase implements MatFormFieldControl<
332332

333333
/** Does some manual dirty checking on the native input `value` property. */
334334
protected _dirtyCheckNativeValue() {
335-
const newValue = this.value;
335+
const newValue = this._elementRef.nativeElement.value;
336336

337337
if (this._previousNativeValue !== newValue) {
338338
this._previousNativeValue = newValue;

0 commit comments

Comments
 (0)