From 219a8ae30cfa65f88e600aee21fdb1c3339ba1e0 Mon Sep 17 00:00:00 2001 From: Will Howell Date: Thu, 13 Jul 2017 20:48:29 -0400 Subject: [PATCH] fix(input): placeholder covering value when using OnPush (#5660) --- src/demo-app/input/input-demo.html | 5 +++++ src/demo-app/input/input-demo.ts | 8 ++++++- src/lib/input/input-container.spec.ts | 31 ++++++++++++++++++++++++++- src/lib/input/input-container.ts | 6 ++++++ 4 files changed, 48 insertions(+), 2 deletions(-) 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 2687fcef8f90..e978db4d3e7e 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() {