Skip to content

Commit 8482bbf

Browse files
authored
feat(autocomplete): support static placeholders (#3115)
1 parent 4f101a1 commit 8482bbf

File tree

3 files changed

+63
-8
lines changed

3 files changed

+63
-8
lines changed

src/demo-app/autocomplete/autocomplete-demo.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<div>Reactive value: {{ stateCtrl.value | json }}</div>
77
<div>Reactive dirty: {{ stateCtrl.dirty }}</div>
88

9-
<md-input-container>
9+
<md-input-container floatPlaceholder="never">
1010
<input mdInput placeholder="State" [mdAutocomplete]="reactiveAuto" [formControl]="stateCtrl">
1111
</md-input-container>
1212

src/lib/autocomplete/autocomplete-trigger.ts

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import {Subject} from 'rxjs/Subject';
2525
import 'rxjs/add/observable/merge';
2626
import 'rxjs/add/operator/startWith';
2727
import 'rxjs/add/operator/switchMap';
28-
import {MdInputContainer, FloatPlaceholderType} from '../input/input-container';
28+
import {MdInputContainer} from '../input/input-container';
2929

3030
/**
3131
* The following style constants are necessary to save here in order
@@ -81,6 +81,9 @@ export class MdAutocompleteTrigger implements AfterContentInit, ControlValueAcce
8181
/** Stream of blur events that should close the panel. */
8282
private _blurStream = new Subject<any>();
8383

84+
/** Whether or not the placeholder state is being overridden. */
85+
private _manuallyFloatingPlaceholder = false;
86+
8487
/** View -> model callback called when value changes */
8588
_onChange = (value: any) => {};
8689

@@ -134,7 +137,7 @@ export class MdAutocompleteTrigger implements AfterContentInit, ControlValueAcce
134137
}
135138

136139
this._panelOpen = true;
137-
this._floatPlaceholder('always');
140+
this._floatPlaceholder();
138141
}
139142

140143
/** Closes the autocomplete suggestion panel. */
@@ -144,7 +147,7 @@ export class MdAutocompleteTrigger implements AfterContentInit, ControlValueAcce
144147
}
145148

146149
this._panelOpen = false;
147-
this._floatPlaceholder('auto');
150+
this._resetPlaceholder();
148151
}
149152

150153
/**
@@ -237,9 +240,18 @@ export class MdAutocompleteTrigger implements AfterContentInit, ControlValueAcce
237240
* This causes the value to jump when selecting an option with the mouse.
238241
* This method manually floats the placeholder until the panel can be closed.
239242
*/
240-
private _floatPlaceholder(state: FloatPlaceholderType): void {
241-
if (this._inputContainer) {
242-
this._inputContainer.floatPlaceholder = state;
243+
private _floatPlaceholder(): void {
244+
if (this._inputContainer && this._inputContainer.floatPlaceholder === 'auto') {
245+
this._inputContainer.floatPlaceholder = 'always';
246+
this._manuallyFloatingPlaceholder = true;
247+
}
248+
}
249+
250+
/** If the placeholder has been manually elevated, return it to its normal state. */
251+
private _resetPlaceholder(): void {
252+
if (this._manuallyFloatingPlaceholder) {
253+
this._inputContainer.floatPlaceholder = 'auto';
254+
this._manuallyFloatingPlaceholder = false;
243255
}
244256
}
245257

src/lib/autocomplete/autocomplete.spec.ts

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,48 @@ describe('MdAutocomplete', () => {
219219
.toBe(false, `Expected panel state to stay closed.`);
220220
});
221221

222+
it('should not mess with placeholder placement if set to never', async(() => {
223+
fixture.componentInstance.placeholder = 'never';
224+
fixture.detectChanges();
225+
226+
fixture.componentInstance.trigger.openPanel();
227+
expect(fixture.componentInstance.inputContainer.floatPlaceholder)
228+
.toEqual('never', 'Expected placeholder to stay static.');
229+
230+
fixture.whenStable().then(() => {
231+
fixture.detectChanges();
232+
233+
const options =
234+
overlayContainerElement.querySelectorAll('md-option') as NodeListOf<HTMLElement>;
235+
options[1].click();
236+
fixture.detectChanges();
237+
238+
expect(fixture.componentInstance.inputContainer.floatPlaceholder)
239+
.toEqual('never', 'Expected placeholder to stay in static state after close.');
240+
});
241+
}));
242+
243+
it('should not mess with placeholder placement if set to always', async(() => {
244+
fixture.componentInstance.placeholder = 'always';
245+
fixture.detectChanges();
246+
247+
fixture.componentInstance.trigger.openPanel();
248+
expect(fixture.componentInstance.inputContainer.floatPlaceholder)
249+
.toEqual('always', 'Expected placeholder to stay elevated on open.');
250+
251+
fixture.whenStable().then(() => {
252+
fixture.detectChanges();
253+
254+
const options =
255+
overlayContainerElement.querySelectorAll('md-option') as NodeListOf<HTMLElement>;
256+
options[1].click();
257+
fixture.detectChanges();
258+
259+
expect(fixture.componentInstance.inputContainer.floatPlaceholder)
260+
.toEqual('always', 'Expected placeholder to stay elevated after close.');
261+
});
262+
}));
263+
222264
});
223265

224266
it('should have the correct text direction in RTL', () => {
@@ -822,7 +864,7 @@ describe('MdAutocomplete', () => {
822864

823865
@Component({
824866
template: `
825-
<md-input-container>
867+
<md-input-container [floatPlaceholder]="placeholder">
826868
<input mdInput placeholder="State" [mdAutocomplete]="auto" [formControl]="stateCtrl">
827869
</md-input-container>
828870
@@ -837,6 +879,7 @@ class SimpleAutocomplete implements OnDestroy {
837879
stateCtrl = new FormControl();
838880
filteredStates: any[];
839881
valueSub: Subscription;
882+
placeholder = 'auto';
840883

841884
@ViewChild(MdAutocompleteTrigger) trigger: MdAutocompleteTrigger;
842885
@ViewChild(MdAutocomplete) panel: MdAutocomplete;

0 commit comments

Comments
 (0)