11import {
22 AfterViewInit ,
33 Component ,
4+ Directive ,
45 ElementRef ,
56 EventEmitter ,
67 HostBinding ,
1415 forwardRef
1516} from '@angular/core' ;
1617import { NG_VALUE_ACCESSOR , ControlValueAccessor } from '@angular/forms' ;
17- import { MDCTextfieldAdapter } from './textfield-adapter' ;
18+ import { EventRegistry } from '../common/event-registry' ;
19+ import { toBoolean } from '../common/boolean-property' ;
20+ import { Ripple } from '.././ripple/ripple.directive' ;
1821
22+ import { MDCTextfieldAdapter } from './textfield-adapter' ;
1923import { MDCTextfieldFoundation } from '@material/textfield' ;
2024
2125export const MD_TEXTFIELD_CONTROL_VALUE_ACCESSOR : Provider = {
@@ -24,7 +28,23 @@ export const MD_TEXTFIELD_CONTROL_VALUE_ACCESSOR: Provider = {
2428 multi : true
2529} ;
2630
27- type UnlistenerMap = WeakMap < EventListener , Function > ;
31+ @Directive ( {
32+ selector : '[mdc-textfield-helptext]'
33+ } )
34+ export class TextfieldHelptextDirective {
35+ @Input ( ) id : string ;
36+ @Input ( ) persistent : boolean ;
37+ @Input ( ) validation : boolean ;
38+ @HostBinding ( 'class.mdc-textfield-helptext' ) isHostClass = true ;
39+ @HostBinding ( 'class.mdc-textfield-helptext--persistent' ) get classPersistent ( ) : string {
40+ return this . persistent ? 'mdc-textfield-helptext--persistent' : '' ;
41+ }
42+ @HostBinding ( 'class.mdc-textfield-helptext--validation-msg' ) get classValidation ( ) : string {
43+ return this . validation ? 'mdc-textfield-helptext--validation-msg' : '' ;
44+ }
45+
46+ constructor ( public elementRef : ElementRef ) { }
47+ }
2848
2949@Component ( {
3050 selector : 'mdc-textfield' ,
@@ -55,22 +75,23 @@ type UnlistenerMap = WeakMap<EventListener, Function>;
5575 [type]="type"
5676 [id]="id"
5777 [attr.name]="name"
58- [attr.aria-controls]="labelId"
5978 [(ngModel)]="value"
6079 [placeholder]="placeholder ? placeholder : ''"
6180 [tabindex]="tabindex"
6281 [maxlength]="maxlength"
6382 [disabled]="disabled"
6483 [required]="required"
65- [attr.tabindex]="tabindex"
6684 (focus)="onFocus($event)"
6785 (keydown)="onKeyDown($event)"
6886 (blur)="onBlur($event)"
6987 (input)="onInput($event)" />
7088 <label #inputlabel [attr.for]="id" class="mdc-textfield__label" *ngIf="!placeholder">{{label}}</label>
7189` ,
7290 encapsulation : ViewEncapsulation . None ,
73- providers : [ MD_TEXTFIELD_CONTROL_VALUE_ACCESSOR ]
91+ providers : [
92+ MD_TEXTFIELD_CONTROL_VALUE_ACCESSOR ,
93+ ] ,
94+ viewProviders : [ Ripple ]
7495} )
7596export class TextfieldComponent implements AfterViewInit , OnDestroy {
7697 @Input ( ) id : string ;
@@ -86,7 +107,6 @@ export class TextfieldComponent implements AfterViewInit, OnDestroy {
86107 }
87108 @Input ( ) dense : boolean ;
88109 @Input ( ) required : boolean ;
89- @Input ( ) labelId : string ;
90110 @Input ( ) label : string ;
91111 @Input ( ) placeholder : string ;
92112 @Input ( ) tabindex : number ;
@@ -111,100 +131,87 @@ export class TextfieldComponent implements AfterViewInit, OnDestroy {
111131 }
112132 @ViewChild ( 'input' ) public inputEl : ElementRef ;
113133 @ViewChild ( 'inputlabel' ) public inputLabel : ElementRef ;
134+ @ViewChild ( TextfieldHelptextDirective ) helpText : TextfieldHelptextDirective ;
114135
115136 onTouched : ( ) => any = ( ) => { } ;
116137
117138 private _controlValueAccessorChangeFn : ( value : any ) => void = ( value ) => { } ;
118- private _unlisteners : Map < string , UnlistenerMap > = new Map < string , UnlistenerMap > ( ) ;
119139
120140 private _mdcAdapter : MDCTextfieldAdapter = {
121141 addClass : ( className : string ) => {
122- const { _renderer : renderer , _root : root } = this ;
123- renderer . addClass ( root . nativeElement , className ) ;
142+ this . _renderer . addClass ( this . _root . nativeElement , className ) ;
124143 } ,
125144 removeClass : ( className : string ) => {
126- const { _renderer : renderer , _root : root } = this ;
127- renderer . removeClass ( root . nativeElement , className ) ;
145+ this . _renderer . removeClass ( this . _root . nativeElement , className ) ;
128146 } ,
129147 addClassToLabel : ( className : string ) => {
130- const { _renderer : renderer , _root : root } = this ;
131148 if ( this . inputLabel ) {
132149 if ( this . label && ! this . fullwidth ) {
133- renderer . addClass ( this . inputLabel . nativeElement , className ) ;
150+ this . _renderer . addClass ( this . inputLabel . nativeElement , className ) ;
134151 }
135152 }
136153 } ,
137154 removeClassFromLabel : ( className : string ) => {
138- const { _renderer : renderer , _root : root } = this ;
139155 if ( this . inputLabel ) {
140156 if ( this . label && ! this . fullwidth ) {
141- renderer . removeClass ( this . inputLabel . nativeElement , className ) ;
157+ this . _renderer . removeClass ( this . inputLabel . nativeElement , className ) ;
142158 }
143159 }
144160 } ,
145161 addClassToHelptext : ( className : string ) => {
146- const { _renderer : renderer , _root : root } = this ;
147- if ( root . nativeElement . attributes . getNamedItem ( 'aria-controls' ) ) {
148- if ( root . nativeElement . nextElementSibling ) {
149- renderer . addClass ( renderer . nextSibling ( root . nativeElement ) , className ) ;
150- }
162+ if ( this . helpText ) {
163+ this . _renderer . addClass ( this . helpText , className ) ;
151164 }
152165 } ,
153166 removeClassFromHelptext : ( className : string ) => {
154- const { _renderer : renderer , _root : root } = this ;
155- if ( root . nativeElement . attributes . getNamedItem ( 'aria-controls' ) ) {
156- renderer . removeClass ( renderer . nextSibling ( root . nativeElement ) , className ) ;
167+ if ( this . helpText ) {
168+ this . _renderer . removeClass ( this . helpText , className ) ;
157169 }
158170 } ,
159171 registerInputFocusHandler : ( handler : EventListener ) => {
160- if ( this . _root ) {
161- this . listen_ ( 'focus' , handler , this . inputEl ) ;
172+ if ( this . inputEl ) {
173+ this . _registry . listen_ ( this . _renderer , 'focus' , handler , this . inputEl ) ;
162174 }
163175 } ,
164176 deregisterInputFocusHandler : ( handler : EventListener ) => {
165- this . unlisten_ ( 'focus' , handler ) ;
177+ this . _registry . unlisten_ ( 'focus' , handler ) ;
166178 } ,
167179 registerInputBlurHandler : ( handler : EventListener ) => {
168- if ( this . _root ) {
169- this . listen_ ( 'blur' , handler , this . inputEl ) ;
180+ if ( this . inputEl ) {
181+ this . _registry . listen_ ( this . _renderer , 'blur' , handler , this . inputEl ) ;
170182 }
171183 } ,
172184 deregisterInputBlurHandler : ( handler : EventListener ) => {
173- this . unlisten_ ( 'blur' , handler ) ;
185+ this . _registry . unlisten_ ( 'blur' , handler ) ;
174186 } ,
175187 registerInputInputHandler : ( handler : EventListener ) => {
176- if ( this . _root ) {
177- this . listen_ ( 'input' , handler , this . inputEl ) ;
188+ if ( this . inputEl ) {
189+ this . _registry . listen_ ( this . _renderer , 'input' , handler , this . inputEl ) ;
178190 }
179191 } ,
180192 deregisterInputInputHandler : ( handler : EventListener ) => {
181- this . unlisten_ ( 'input' , handler ) ;
193+ this . _registry . unlisten_ ( 'input' , handler ) ;
182194 } ,
183195 registerInputKeydownHandler : ( handler : EventListener ) => {
184- if ( this . _root ) {
185- this . listen_ ( 'keydown' , handler , this . inputEl ) ;
196+ if ( this . inputEl ) {
197+ this . _registry . listen_ ( this . _renderer , 'keydown' , handler , this . inputEl ) ;
186198 }
187199 } ,
188200 deregisterInputKeydownHandler : ( handler : EventListener ) => {
189- this . unlisten_ ( 'keydown' , handler ) ;
201+ this . _registry . unlisten_ ( 'keydown' , handler ) ;
190202 } ,
191203 setHelptextAttr : ( name : string , value : string ) => {
192- const { _renderer : renderer , _root : root } = this ;
193- if ( root . nativeElement . attributes . getNamedItem ( 'aria-controls' ) ) {
194- root . nativeElement . nextElementSibling ? renderer . setAttribute ( root . nativeElement . nextElementSibling , name , value ) : null ;
204+ if ( this . helpText ) {
205+ this . _renderer . setAttribute ( this . helpText . elementRef . nativeElement , name , value ) ;
195206 }
196207 } ,
197208 removeHelptextAttr : ( name : string ) => {
198- const { _renderer : renderer , _root : root } = this ;
199- if ( root . nativeElement . attributes . getNamedItem ( 'aria-controls' ) ) {
200- return root . nativeElement . nextElementSibling ? renderer . removeAttribute ( root . nativeElement . nextElementSibling , name ) : null ;
209+ if ( this . helpText ) {
210+ this . _renderer . removeAttribute ( this . helpText . elementRef . nativeElement , name ) ;
201211 }
202212 } ,
203213 helptextHasClass : ( className : string ) => {
204- const { _renderer : renderer , _root : root } = this ;
205- if ( root . nativeElement . attributes . getNamedItem ( 'aria-controls' ) ) {
206- return root . nativeElement . nextElementSibling ? root . nativeElement . nextElementSibling . classList . contains ( className ) : false ;
207- }
214+ return this . helpText ? this . helpText . elementRef . nativeElement . classList . contains ( className ) : false ;
208215 } ,
209216 getNativeInput : ( ) => {
210217 return this . inputEl ? this . inputEl . nativeElement : null ;
@@ -218,7 +225,11 @@ export class TextfieldComponent implements AfterViewInit, OnDestroy {
218225 setDisabled : Function
219226 } = new MDCTextfieldFoundation ( this . _mdcAdapter ) ;
220227
221- constructor ( private _renderer : Renderer2 , private _root : ElementRef ) { }
228+ constructor (
229+ private _renderer : Renderer2 ,
230+ private _root : ElementRef ,
231+ private _registry : EventRegistry ,
232+ public ripple : Ripple ) { }
222233
223234 ngAfterViewInit ( ) {
224235 this . _foundation . init ( ) ;
@@ -264,24 +275,4 @@ export class TextfieldComponent implements AfterViewInit, OnDestroy {
264275 registerOnTouched ( fn : any ) {
265276 this . onTouched = fn ;
266277 }
267-
268- listen_ ( type : string , listener : EventListener , ref : ElementRef = this . _root ) {
269- if ( ! this . _unlisteners . has ( type ) ) {
270- this . _unlisteners . set ( type , new WeakMap < EventListener , Function > ( ) ) ;
271- }
272- const unlistener = this . _renderer . listen ( ref . nativeElement , type , listener ) ;
273- this . _unlisteners . get ( type ) . set ( listener , unlistener ) ;
274- }
275-
276- unlisten_ ( type : string , listener : EventListener ) {
277- if ( ! this . _unlisteners . has ( type ) ) {
278- return ;
279- }
280- const unlisteners = this . _unlisteners . get ( type ) ;
281- if ( ! unlisteners . has ( listener ) ) {
282- return ;
283- }
284- unlisteners . get ( listener ) ( ) ;
285- unlisteners . delete ( listener ) ;
286- }
287- }
278+ }
0 commit comments