diff --git a/src/demo-app/input/input-demo.html b/src/demo-app/input/input-demo.html
index 475633c54941..f3b5cc952d94 100644
--- a/src/demo-app/input/input-demo.html
+++ b/src/demo-app/input/input-demo.html
@@ -382,6 +382,11 @@
Textarea
+
+
+
+
+
diff --git a/src/demo-app/input/input-demo.ts b/src/demo-app/input/input-demo.ts
index 675c10acd995..a76d2165ed09 100644
--- a/src/demo-app/input/input-demo.ts
+++ b/src/demo-app/input/input-demo.ts
@@ -1,4 +1,4 @@
-import {Component} from '@angular/core';
+import { Component, ChangeDetectionStrategy } from '@angular/core';
import {FormControl, Validators} from '@angular/forms';
@@ -8,6 +8,7 @@ const EMAIL_REGEX = /^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA
@Component({
moduleId: module.id,
+ changeDetection: ChangeDetectionStrategy.OnPush,
selector: 'input-demo',
templateUrl: 'input-demo.html',
styleUrls: ['input-demo.css'],
@@ -38,8 +39,13 @@ export class InputDemo {
rows = 8;
formControl = new FormControl('hello', Validators.required);
emailFormControl = new FormControl('', [Validators.required, Validators.pattern(EMAIL_REGEX)]);
+ delayedFormControl = new FormControl('');
model = 'hello';
+ constructor() {
+ setTimeout(() => this.delayedFormControl.setValue('hello'), 100);
+ }
+
addABunch(n: number) {
for (let x = 0; x < n; x++) {
this.items.push({ value: ++max });
diff --git a/src/lib/input/input-container.spec.ts b/src/lib/input/input-container.spec.ts
index ebf4fd8f851a..f1f27bf3c1da 100644
--- a/src/lib/input/input-container.spec.ts
+++ b/src/lib/input/input-container.spec.ts
@@ -1,5 +1,5 @@
import {async, ComponentFixture, inject, TestBed} from '@angular/core/testing';
-import {Component, ViewChild} from '@angular/core';
+import {Component, ViewChild, ChangeDetectionStrategy} from '@angular/core';
import {
FormControl,
FormGroup,
@@ -61,6 +61,7 @@ describe('MdInputContainer without forms', function () {
MdInputContainerWithValueBinding,
MdTextareaWithBindings,
MdInputContainerWithNgIf,
+ MdInputContainerOnPush,
],
});
@@ -587,6 +588,22 @@ describe('MdInputContainer without forms', function () {
expect(prefixEl.nativeElement.innerText.trim()).toEqual('Prefix');
expect(suffixEl.nativeElement.innerText.trim()).toEqual('Suffix');
});
+
+ it('should update empty class when value changes programmatically and OnPush', () => {
+ let fixture = TestBed.createComponent(MdInputContainerOnPush);
+ fixture.detectChanges();
+
+ let component = fixture.componentInstance;
+ let placeholder = fixture.debugElement
+ .query(By.css('.mat-input-placeholder')).nativeElement;
+
+ expect(placeholder.classList).toContain('mat-empty', 'Input initially empty');
+
+ component.formControl.setValue('something');
+ fixture.detectChanges();
+
+ expect(placeholder.classList).not.toContain('mat-empty', 'Input no longer empty');
+ });
});
describe('MdInputContainer with forms', () => {
@@ -1201,3 +1218,15 @@ class MdInputContainerWithPrefixAndSuffix {}
class MdInputContainerWithNgIf {
renderInput = true;
}
+
+@Component({
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ template: `
+
+
+
+ `
+})
+class MdInputContainerOnPush {
+ formControl = new FormControl('');
+}
diff --git a/src/lib/input/input-container.ts b/src/lib/input/input-container.ts
index 07fea22ced03..189c038fd687 100644
--- a/src/lib/input/input-container.ts
+++ b/src/lib/input/input-container.ts
@@ -410,6 +410,12 @@ export class MdInputContainer implements AfterViewInit, AfterContentInit, AfterC
// Re-validate when things change.
this._hintChildren.changes.subscribe(() => this._processHints());
this._mdInputChild._placeholderChange.subscribe(() => this._validatePlaceholders());
+
+ // Mark for check when the input's value changes to recalculate whether input is empty
+ const control = this._mdInputChild._ngControl;
+ if (control && control.valueChanges) {
+ control.valueChanges.subscribe(() => this._changeDetectorRef.markForCheck());
+ }
}
ngAfterContentChecked() {