fix(autocomplete): placeholder not resetting properly (#6141)

Fixes the following regressions that were introduced by the switch to OnPush change detection:
* The floating placeholder not resetting when the user closes the panel without selecting a value.
* The placeholder overlapping the input value when the autocomplete has a preselected value and `floatPlaceholder="never"`.
This commit is contained in:
Kristiyan Kostadinov
2017-08-03 00:57:32 +02:00
committed by tinayuangao
parent a780052090
commit e4e7ee90f8
4 changed files with 72 additions and 6 deletions
+10 -1
View File
@@ -409,9 +409,18 @@ export class MdAutocompleteTrigger implements ControlValueAccessor, OnDestroy {
private _setTriggerValue(value: any): void {
const toDisplay = this.autocomplete.displayWith ? this.autocomplete.displayWith(value) : value;
// Simply falling back to an empty string if the display value is falsy does not work properly.
// The display value can also be the number zero and shouldn't fall back to an empty string.
this._element.nativeElement.value = toDisplay != null ? toDisplay : '';
const inputValue = toDisplay != null ? toDisplay : '';
// If it's used in a Material container, we should set it through
// the property so it can go through the change detection.
if (this._inputContainer) {
this._inputContainer._mdInputChild.value = inputValue;
} else {
this._element.nativeElement.value = inputValue;
}
}
/**
+33 -3
View File
@@ -54,7 +54,8 @@ describe('MdAutocomplete', () => {
AutocompleteWithNumbers,
AutocompleteWithOnPushDelay,
AutocompleteWithNativeInput,
AutocompleteWithoutPanel
AutocompleteWithoutPanel,
AutocompleteWithFormsAndNonfloatingPlaceholder
],
providers: [
{provide: OverlayContainer, useFactory: () => {
@@ -1314,6 +1315,21 @@ describe('MdAutocomplete', () => {
}).toThrow(getMdAutocompleteMissingPanelError());
}));
it('should hide the placeholder with a preselected form control value ' +
'and a disabled floating placeholder', fakeAsync(() => {
const fixture = TestBed.createComponent(AutocompleteWithFormsAndNonfloatingPlaceholder);
fixture.detectChanges();
tick();
fixture.detectChanges();
const input = fixture.nativeElement.querySelector('input');
const placeholder = fixture.nativeElement.querySelector('.mat-input-placeholder');
expect(input.value).toBe('California');
expect(placeholder.classList).not.toContain('mat-empty');
}));
});
it('should have correct width when opened', () => {
@@ -1501,7 +1517,6 @@ class AutocompleteWithoutForms {
onInput(value: any) {
this.filteredStates = this.states.filter(s => new RegExp(value, 'gi').test(s));
}
}
@@ -1531,7 +1546,6 @@ class AutocompleteWithNgModel {
onInput(value: any) {
this.filteredStates = this.states.filter(s => new RegExp(value, 'gi').test(s));
}
}
@Component({
@@ -1611,3 +1625,19 @@ class AutocompleteWithNativeInput {
class AutocompleteWithoutPanel {
@ViewChild(MdAutocompleteTrigger) trigger: MdAutocompleteTrigger;
}
@Component({
template: `
<md-input-container floatPlaceholder="never">
<input placeholder="State" mdInput [mdAutocomplete]="auto" [formControl]="formControl">
</md-input-container>
<md-autocomplete #auto="mdAutocomplete">
<md-option value="California">California</md-option>
</md-autocomplete>
`
})
class AutocompleteWithFormsAndNonfloatingPlaceholder {
formControl = new FormControl('California');
}
+19
View File
@@ -566,6 +566,25 @@ describe('MdInputContainer without forms', function () {
expect(labelEl.classList).not.toContain('mat-float');
});
it('should be able to toggle the floating placeholder programmatically', () => {
const fixture = TestBed.createComponent(MdInputContainerWithId);
fixture.detectChanges();
const inputContainer = fixture.debugElement.query(By.directive(MdInputContainer));
const containerInstance = inputContainer.componentInstance as MdInputContainer;
const placeholder = inputContainer.nativeElement.querySelector('.mat-input-placeholder');
expect(containerInstance.floatPlaceholder).toBe('auto');
expect(placeholder.classList).toContain('mat-empty', 'Expected input to be considered empty.');
containerInstance.floatPlaceholder = 'always';
fixture.detectChanges();
expect(placeholder.classList)
.not.toContain('mat-empty', 'Expected input to be considered not empty.');
});
it('should not have prefix and suffix elements when none are specified', () => {
let fixture = TestBed.createComponent(MdInputContainerWithId);
fixture.detectChanges();
+10 -2
View File
@@ -207,7 +207,12 @@ export class MdInputDirective implements OnChanges, OnDestroy, DoCheck {
/** The input element's value. */
get value() { return this._elementRef.nativeElement.value; }
set value(value: string) { this._elementRef.nativeElement.value = value; }
set value(value: string) {
if (value !== this.value) {
this._elementRef.nativeElement.value = value;
this._stateChanges.next();
}
}
/** Whether the input is empty. */
get empty() {
@@ -443,7 +448,10 @@ export class MdInputContainer implements AfterViewInit, AfterContentInit, AfterC
@Input()
get floatPlaceholder() { return this._floatPlaceholder; }
set floatPlaceholder(value: FloatPlaceholderType) {
this._floatPlaceholder = value || this._placeholderOptions.float || 'auto';
if (value !== this._floatPlaceholder) {
this._floatPlaceholder = value || this._placeholderOptions.float || 'auto';
this._changeDetectorRef.markForCheck();
}
}
private _floatPlaceholder: FloatPlaceholderType;