From 0c381fbbeda57366eeb585ee34bdf93b12bfc7b7 Mon Sep 17 00:00:00 2001 From: crisbeto Date: Wed, 28 Dec 2016 13:03:49 +0200 Subject: [PATCH] fix(input): not floating the label when updating the value programmatically with reactive forms Fixes the input placeholder not being floating when the value is updated programmatically via `FormControl.setValue`. This was because the listener that handles the value changes gets initialized before the `FormControl`. Fixes #2441. --- src/lib/input/input-container.spec.ts | 29 ++++++++++++++++++++++++--- src/lib/input/input-container.ts | 13 ++++++------ 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/src/lib/input/input-container.spec.ts b/src/lib/input/input-container.spec.ts index 335acfaf3c40..9839cec44472 100644 --- a/src/lib/input/input-container.spec.ts +++ b/src/lib/input/input-container.spec.ts @@ -1,9 +1,9 @@ import {async, TestBed, inject} from '@angular/core/testing'; import {Component} from '@angular/core'; -import {FormsModule, ReactiveFormsModule} from '@angular/forms'; +import {FormsModule, ReactiveFormsModule, FormControl} from '@angular/forms'; import {By} from '@angular/platform-browser'; import {MdInputModule} from './input'; -import {MdInputContainer} from './input-container'; +import {MdInputContainer, MdInputDirective} from './input-container'; import {Platform} from '../core/platform/platform'; import {PlatformModule} from '../core/platform/index'; import { @@ -41,7 +41,8 @@ describe('MdInputContainer', function () { MdInputContainerZeroTestController, MdTextareaWithBindings, MdInputContainerWithDisabled, - MdInputContainerMissingMdInputTestController + MdInputContainerMissingMdInputTestController, + MdInputContainerWithFormControl ], }); @@ -293,6 +294,21 @@ describe('MdInputContainer', function () { const textarea: HTMLTextAreaElement = fixture.nativeElement.querySelector('textarea'); expect(textarea).not.toBeNull(); }); + + it('should update the value when using FormControl.setValue', () => { + let fixture = TestBed.createComponent(MdInputContainerWithFormControl); + fixture.detectChanges(); + + let input = fixture.debugElement.query(By.directive(MdInputDirective)) + .injector.get(MdInputDirective) as MdInputDirective; + + expect(input.value).toBeFalsy(); + + fixture.componentInstance.formControl.setValue('something'); + + expect(input.value).toBe('something'); + }); + }); @Component({ @@ -446,6 +462,13 @@ class MdTextareaWithBindings { }) class MdInputContainerMissingMdInputTestController {} +@Component({ + template: `` +}) +class MdInputContainerWithFormControl { + formControl = new FormControl(); +} + /** * Gets a RegExp used to detect an angular wrapped error message. * See https://github.com/angular/angular/issues/8348 diff --git a/src/lib/input/input-container.ts b/src/lib/input/input-container.ts index 37d18f2ff0db..265abd4e6b03 100644 --- a/src/lib/input/input-container.ts +++ b/src/lib/input/input-container.ts @@ -11,7 +11,8 @@ import { Optional, Output, EventEmitter, - Renderer + Renderer, + OnInit, } from '@angular/core'; import {coerceBooleanProperty} from '../core'; import {NgControl} from '@angular/forms'; @@ -77,7 +78,7 @@ export class MdHint { '(input)': '_onInput()', } }) -export class MdInputDirective implements AfterContentInit { +export class MdInputDirective implements AfterContentInit, OnInit { /** Whether the element is disabled. */ @Input() get disabled() { return this._disabled; } @@ -142,14 +143,14 @@ export class MdInputDirective implements AfterContentInit { constructor(private _elementRef: ElementRef, private _renderer: Renderer, - @Optional() public _ngControl: NgControl) { + @Optional() public _ngControl: NgControl) { } + + ngOnInit() { // Force setter to be called in case id was not specified. this.id = this.id; if (this._ngControl && this._ngControl.valueChanges) { - this._ngControl.valueChanges.subscribe((value) => { - this.value = value; - }); + this._ngControl.valueChanges.subscribe(value => this.value = value); } }