diff --git a/src/lib/autocomplete/autocomplete-trigger.ts b/src/lib/autocomplete/autocomplete-trigger.ts
index cdc00c36aeba..7710bd335033 100644
--- a/src/lib/autocomplete/autocomplete-trigger.ts
+++ b/src/lib/autocomplete/autocomplete-trigger.ts
@@ -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;
+ }
}
/**
diff --git a/src/lib/autocomplete/autocomplete.spec.ts b/src/lib/autocomplete/autocomplete.spec.ts
index d043c13ee17f..495af40ba1a9 100644
--- a/src/lib/autocomplete/autocomplete.spec.ts
+++ b/src/lib/autocomplete/autocomplete.spec.ts
@@ -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: `
+
+
+
+
+
+ California
+
+ `
+})
+class AutocompleteWithFormsAndNonfloatingPlaceholder {
+ formControl = new FormControl('California');
+}
diff --git a/src/lib/input/input-container.spec.ts b/src/lib/input/input-container.spec.ts
index cb31144b2670..58cd7889fbc4 100644
--- a/src/lib/input/input-container.spec.ts
+++ b/src/lib/input/input-container.spec.ts
@@ -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();
diff --git a/src/lib/input/input-container.ts b/src/lib/input/input-container.ts
index 3227965b24b2..4d065e68e381 100644
--- a/src/lib/input/input-container.ts
+++ b/src/lib/input/input-container.ts
@@ -208,7 +208,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() {
@@ -429,7 +434,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;