@@ -75,53 +75,71 @@ export class MdHint {
7575 ` ,
7676 host : {
7777 'class' : 'md-input-element' ,
78+ // Native input properties that are overwritten by Angular inputs need to be synced with
79+ // the native input element. Otherwise property bindings for those don't work.
7880 '[id]' : 'id' ,
81+ '[placeholder]' : 'placeholder' ,
82+ '[disabled]' : 'disabled' ,
83+ '[required]' : 'required' ,
7984 '(blur)' : '_onBlur()' ,
8085 '(focus)' : '_onFocus()' ,
8186 '(input)' : '_onInput()' ,
8287 }
8388} )
8489export class MdInputDirective implements AfterContentInit {
90+
91+ /** Variables used as cache for getters and setters. */
92+ private _type = 'text' ;
93+ private _placeholder : string = '' ;
94+ private _disabled = false ;
95+ private _required = false ;
96+ private _id : string ;
97+ private _cachedUid : string ;
98+
99+ /** The element's value. */
100+ value : any ;
101+
102+ /** Whether the element is focused or not. */
103+ focused = false ;
104+
85105 /** Whether the element is disabled. */
86106 @Input ( )
87107 get disabled ( ) { return this . _disabled ; }
88108 set disabled ( value : any ) { this . _disabled = coerceBooleanProperty ( value ) ; }
89- private _disabled = false ;
90109
91110 /** Unique id of the element. */
92111 @Input ( )
93112 get id ( ) { return this . _id ; } ;
94- set id ( value : string ) { this . _id = value || this . _uid ; }
95- private _id : string ;
113+ set id ( value : string ) { this . _id = value || this . _uid ; }
96114
97115 /** Placeholder attribute of the element. */
98116 @Input ( )
99117 get placeholder ( ) { return this . _placeholder ; }
100118 set placeholder ( value : string ) {
101- if ( this . _placeholder != value ) {
119+ if ( this . _placeholder !== value ) {
102120 this . _placeholder = value ;
103121 this . _placeholderChange . emit ( this . _placeholder ) ;
104122 }
105123 }
106- private _placeholder = '' ;
107-
108124 /** Whether the element is required. */
109125 @Input ( )
110126 get required ( ) { return this . _required ; }
111127 set required ( value : any ) { this . _required = coerceBooleanProperty ( value ) ; }
112- private _required = false ;
113128
114129 /** Input type of the element. */
115130 @Input ( )
116131 get type ( ) { return this . _type ; }
117132 set type ( value : string ) {
118133 this . _type = value || 'text' ;
119134 this . _validateType ( ) ;
120- }
121- private _type = 'text' ;
122135
123- /** The element's value. */
124- value : any ;
136+ // When using Angular inputs, developers are no longer able to set the properties on the native
137+ // input element. To ensure that bindings for `type` work, we need to sync the setter
138+ // with the native property. Textarea elements don't support the type property or attribute.
139+ if ( ! this . _isTextarea ( ) && getSupportedInputTypes ( ) . has ( this . _type ) ) {
140+ this . _renderer . setElementProperty ( this . _elementRef . nativeElement , 'type' , this . _type ) ;
141+ }
142+ }
125143
126144 /**
127145 * Emits an event when the placeholder changes so that the `md-input-container` can re-validate.
@@ -130,10 +148,7 @@ export class MdInputDirective implements AfterContentInit {
130148
131149 get empty ( ) { return ( this . value == null || this . value === '' ) && ! this . _isNeverEmpty ( ) ; }
132150
133- focused = false ;
134-
135151 private get _uid ( ) { return this . _cachedUid = this . _cachedUid || `md-input-${ nextUniqueId ++ } ` ; }
136- private _cachedUid : string ;
137152
138153 private _neverEmptyInputTypes = [
139154 'date' ,
@@ -172,12 +187,18 @@ export class MdInputDirective implements AfterContentInit {
172187
173188 /** Make sure the input is a supported type. */
174189 private _validateType ( ) {
175- if ( MD_INPUT_INVALID_TYPES . indexOf ( this . _type ) != - 1 ) {
190+ if ( MD_INPUT_INVALID_TYPES . indexOf ( this . _type ) !== - 1 ) {
176191 throw new MdInputContainerUnsupportedTypeError ( this . _type ) ;
177192 }
178193 }
179194
180- private _isNeverEmpty ( ) { return this . _neverEmptyInputTypes . indexOf ( this . _type ) != - 1 ; }
195+ private _isNeverEmpty ( ) { return this . _neverEmptyInputTypes . indexOf ( this . _type ) !== - 1 ; }
196+
197+ /** Determines if the component host is a textarea. If not recognizable it returns false. */
198+ private _isTextarea ( ) {
199+ let nativeElement = this . _elementRef . nativeElement ;
200+ return nativeElement ? nativeElement . nodeName . toLowerCase ( ) === 'textarea' : false ;
201+ }
181202}
182203
183204
0 commit comments