@@ -95,6 +95,8 @@ class MDCTextFieldFoundation extends MDCFoundation {
95
95
this . receivedUserInput_ = false ;
96
96
/** @private {boolean} */
97
97
this . useCustomValidityChecking_ = false ;
98
+ /** @private {boolean} */
99
+ this . isValid_ = true ;
98
100
/** @private {function(): undefined} */
99
101
this . inputFocusHandler_ = ( ) => this . activateFocus ( ) ;
100
102
/** @private {function(): undefined} */
@@ -112,8 +114,9 @@ class MDCTextFieldFoundation extends MDCFoundation {
112
114
init ( ) {
113
115
this . adapter_ . addClass ( MDCTextFieldFoundation . cssClasses . UPGRADED ) ;
114
116
// Ensure label does not collide with any pre-filled value.
115
- if ( this . getNativeInput_ ( ) . value && this . label_ ) {
116
- this . label_ . floatAbove ( ) ;
117
+ if ( this . label_ && this . getValue ( ) ) {
118
+ this . label_ . styleFloat (
119
+ this . getValue ( ) , this . isFocused_ , this . isBadInput_ ( ) ) ;
117
120
}
118
121
119
122
if ( this . adapter_ . isFocused ( ) ) {
@@ -181,21 +184,22 @@ class MDCTextFieldFoundation extends MDCFoundation {
181
184
* Activates the text field focus state.
182
185
*/
183
186
activateFocus ( ) {
184
- const { FOCUSED } = MDCTextFieldFoundation . cssClasses ;
185
- this . adapter_ . addClass ( FOCUSED ) ;
187
+ this . isFocused_ = true ;
188
+ this . styleFocused_ ( this . isFocused_ ) ;
186
189
if ( this . bottomLine_ ) {
187
190
this . bottomLine_ . activate ( ) ;
188
191
}
189
192
if ( this . outline_ ) {
190
193
this . updateOutline ( ) ;
191
194
}
192
195
if ( this . label_ ) {
193
- this . label_ . floatAbove ( ) ;
196
+ this . label_ . styleShake ( this . isValid ( ) , this . isFocused_ ) ;
197
+ this . label_ . styleFloat (
198
+ this . getValue ( ) , this . isFocused_ , this . isBadInput_ ( ) ) ;
194
199
}
195
200
if ( this . helperText_ ) {
196
201
this . helperText_ . showToScreenReader ( ) ;
197
202
}
198
- this . isFocused_ = true ;
199
203
}
200
204
201
205
/**
@@ -233,54 +237,67 @@ class MDCTextFieldFoundation extends MDCFoundation {
233
237
}
234
238
235
239
/**
236
- * Deactives the Text Field's focus state.
240
+ * Deactivates the Text Field's focus state.
237
241
*/
238
242
deactivateFocus ( ) {
239
- const { FOCUSED } = MDCTextFieldFoundation . cssClasses ;
243
+ this . isFocused_ = false ;
240
244
const input = this . getNativeInput_ ( ) ;
241
245
const shouldRemoveLabelFloat = ! input . value && ! this . isBadInput_ ( ) ;
242
-
243
- this . isFocused_ = false ;
244
- this . adapter_ . removeClass ( FOCUSED ) ;
246
+ const isValid = this . isValid ( ) ;
247
+ this . styleValidity_ ( isValid ) ;
248
+ this . styleFocused_ ( this . isFocused_ ) ;
245
249
if ( this . label_ ) {
246
- this . label_ . deactivateFocus ( shouldRemoveLabelFloat ) ;
250
+ this . label_ . styleShake ( this . isValid ( ) , this . isFocused_ ) ;
251
+ this . label_ . styleFloat (
252
+ this . getValue ( ) , this . isFocused_ , this . isBadInput_ ( ) ) ;
247
253
}
248
254
if ( shouldRemoveLabelFloat ) {
249
255
this . receivedUserInput_ = false ;
250
256
}
257
+ }
251
258
252
- if ( ! this . useCustomValidityChecking_ ) {
253
- this . changeValidity_ ( input . checkValidity ( ) ) ;
254
- }
259
+ /**
260
+ * @return {string } The value of the input Element.
261
+ */
262
+ getValue ( ) {
263
+ return this . getNativeInput_ ( ) . value ;
255
264
}
256
265
257
266
/**
258
- * Updates the Text Field's valid state based on the supplied validity.
259
- * @param {boolean } isValid
260
- * @private
267
+ * @param {string } value The value to set on the input Element.
261
268
*/
262
- changeValidity_ ( isValid ) {
263
- const { INVALID } = MDCTextFieldFoundation . cssClasses ;
264
- if ( isValid ) {
265
- this . adapter_ . removeClass ( INVALID ) ;
266
- } else {
267
- this . adapter_ . addClass ( INVALID ) ;
268
- }
269
- if ( this . helperText_ ) {
270
- this . helperText_ . setValidity ( isValid ) ;
271
- }
269
+ setValue ( value ) {
270
+ this . getNativeInput_ ( ) . value = value ;
271
+ const isValid = this . isValid ( ) ;
272
+ this . styleValidity_ ( isValid ) ;
272
273
if ( this . label_ ) {
273
- this . label_ . setValidity ( isValid ) ;
274
+ this . label_ . styleShake ( isValid , this . isFocused_ ) ;
275
+ this . label_ . styleFloat (
276
+ this . getValue ( ) , this . isFocused_ , this . isBadInput_ ( ) ) ;
274
277
}
275
278
}
276
279
277
280
/**
278
- * @return {boolean } True if the Text Field input fails validity checks .
279
- * @private
281
+ * @return {boolean } If a custom validity is set, returns that value .
282
+ * Otherwise, returns the result of native validity checks.
280
283
*/
281
- isBadInput_ ( ) {
282
- const input = this . getNativeInput_ ( ) ;
283
- return input . validity ? input . validity . badInput : input . badInput ;
284
+ isValid ( ) {
285
+ return this . useCustomValidityChecking_
286
+ ? this . isValid_ : this . isNativeInputValid_ ( ) ;
287
+ }
288
+
289
+ /**
290
+ * @param {boolean } isValid Sets the validity state of the Text Field.
291
+ */
292
+ setValid ( isValid ) {
293
+ this . useCustomValidityChecking_ = true ;
294
+ this . isValid_ = isValid ;
295
+ // Retrieve from the getter to ensure correct logic is applied.
296
+ isValid = this . isValid ( ) ;
297
+ this . styleValidity_ ( isValid ) ;
298
+ if ( this . label_ ) {
299
+ this . label_ . styleShake ( isValid , this . isFocused_ ) ;
300
+ }
284
301
}
285
302
286
303
/**
@@ -294,17 +311,25 @@ class MDCTextFieldFoundation extends MDCFoundation {
294
311
* @param {boolean } disabled Sets the text-field disabled or enabled.
295
312
*/
296
313
setDisabled ( disabled ) {
297
- const { DISABLED , INVALID } = MDCTextFieldFoundation . cssClasses ;
298
314
this . getNativeInput_ ( ) . disabled = disabled ;
299
- if ( disabled ) {
300
- this . adapter_ . addClass ( DISABLED ) ;
301
- this . adapter_ . removeClass ( INVALID ) ;
302
- } else {
303
- this . adapter_ . removeClass ( DISABLED ) ;
304
- }
305
- if ( this . icon_ ) {
306
- this . icon_ . setDisabled ( disabled ) ;
307
- }
315
+ this . styleDisabled_ ( disabled ) ;
316
+ }
317
+
318
+ /**
319
+ * @return {boolean } True if the Text Field is required.
320
+ */
321
+ isRequired ( ) {
322
+ return this . getNativeInput_ ( ) . required ;
323
+ }
324
+
325
+ /**
326
+ * @param {boolean } isRequired Sets the text-field required or not.
327
+ */
328
+ setRequired ( isRequired ) {
329
+ this . getNativeInput_ ( ) . required = isRequired ;
330
+ // Addition of the asterisk is automatic based on CSS, but validity checking
331
+ // needs to be manually run.
332
+ this . styleValidity_ ( this . isValid ( ) ) ;
308
333
}
309
334
310
335
/**
@@ -316,6 +341,72 @@ class MDCTextFieldFoundation extends MDCFoundation {
316
341
}
317
342
}
318
343
344
+ /**
345
+ * @return {boolean } True if the Text Field input fails in converting the
346
+ * user-supplied value.
347
+ * @private
348
+ */
349
+ isBadInput_ ( ) {
350
+ return this . getNativeInput_ ( ) . validity . badInput ;
351
+ }
352
+
353
+ /**
354
+ * @return {boolean } The result of native validity checking
355
+ * (ValidityState.valid).
356
+ */
357
+ isNativeInputValid_ ( ) {
358
+ return this . getNativeInput_ ( ) . validity . valid ;
359
+ }
360
+
361
+ /**
362
+ * Styles the component based on the validity state.
363
+ * @param {boolean } isValid
364
+ * @private
365
+ */
366
+ styleValidity_ ( isValid ) {
367
+ const { INVALID } = MDCTextFieldFoundation . cssClasses ;
368
+ if ( isValid ) {
369
+ this . adapter_ . removeClass ( INVALID ) ;
370
+ } else {
371
+ this . adapter_ . addClass ( INVALID ) ;
372
+ }
373
+ if ( this . helperText_ ) {
374
+ this . helperText_ . setValidity ( isValid ) ;
375
+ }
376
+ }
377
+
378
+ /**
379
+ * Styles the component based on the focused state.
380
+ * @param {boolean } isFocused
381
+ * @private
382
+ */
383
+ styleFocused_ ( isFocused ) {
384
+ const { FOCUSED } = MDCTextFieldFoundation . cssClasses ;
385
+ if ( isFocused ) {
386
+ this . adapter_ . addClass ( FOCUSED ) ;
387
+ } else {
388
+ this . adapter_ . removeClass ( FOCUSED ) ;
389
+ }
390
+ }
391
+
392
+ /**
393
+ * Styles the component based on the disabled state.
394
+ * @param {boolean } isDisabled
395
+ * @private
396
+ */
397
+ styleDisabled_ ( isDisabled ) {
398
+ const { DISABLED , INVALID } = MDCTextFieldFoundation . cssClasses ;
399
+ if ( isDisabled ) {
400
+ this . adapter_ . addClass ( DISABLED ) ;
401
+ this . adapter_ . removeClass ( INVALID ) ;
402
+ } else {
403
+ this . adapter_ . removeClass ( DISABLED ) ;
404
+ }
405
+ if ( this . icon_ ) {
406
+ this . icon_ . setDisabled ( isDisabled ) ;
407
+ }
408
+ }
409
+
319
410
/**
320
411
* @return {!Element|!NativeInputType } The native text input from the
321
412
* host environment, or a dummy if none exists.
@@ -324,20 +415,14 @@ class MDCTextFieldFoundation extends MDCFoundation {
324
415
getNativeInput_ ( ) {
325
416
return this . adapter_ . getNativeInput ( ) ||
326
417
/** @type {!NativeInputType } */ ( {
327
- checkValidity : ( ) => true ,
328
418
value : '' ,
329
419
disabled : false ,
330
- badInput : false ,
420
+ validity : {
421
+ badInput : false ,
422
+ valid : true ,
423
+ } ,
331
424
} ) ;
332
425
}
333
-
334
- /**
335
- * @param {boolean } isValid Sets the validity state of the Text Field.
336
- */
337
- setValid ( isValid ) {
338
- this . useCustomValidityChecking_ = true ;
339
- this . changeValidity_ ( isValid ) ;
340
- }
341
426
}
342
427
343
428
export default MDCTextFieldFoundation ;
0 commit comments