@@ -51,6 +51,7 @@ import {
51
51
MD_ERROR_GLOBAL_OPTIONS
52
52
} from '../core/error/error-options' ;
53
53
import { Subject } from 'rxjs/Subject' ;
54
+ import { startWith } from '@angular/cdk/rxjs' ;
54
55
55
56
// Invalid input type. Using one of these will throw an MdInputContainerUnsupportedTypeError.
56
57
const MD_INPUT_INVALID_TYPES = [
@@ -100,10 +101,13 @@ export class MdHint {
100
101
@Directive ( {
101
102
selector : 'md-error, mat-error' ,
102
103
host : {
103
- 'class' : 'mat-input-error'
104
+ 'class' : 'mat-input-error' ,
105
+ '[attr.id]' : 'id' ,
104
106
}
105
107
} )
106
- export class MdErrorDirective { }
108
+ export class MdErrorDirective {
109
+ @Input ( ) id : string = `md-input-error-${ nextUniqueId ++ } ` ;
110
+ }
107
111
108
112
/** Prefix to be placed the the front of the input. */
109
113
@Directive ( {
@@ -474,12 +478,11 @@ export class MdInputContainer implements AfterViewInit, AfterContentInit, AfterC
474
478
475
479
ngAfterContentInit ( ) {
476
480
this . _validateInputChild ( ) ;
477
- this . _processHints ( ) ;
478
- this . _validatePlaceholders ( ) ;
479
481
480
482
// Subscribe to changes in the child input state in order to update the container UI.
481
- this . _mdInputChild . _stateChanges . subscribe ( ( ) => {
483
+ startWith . call ( this . _mdInputChild . _stateChanges , null ) . subscribe ( ( ) => {
482
484
this . _validatePlaceholders ( ) ;
485
+ this . _syncAriaDescribedby ( ) ;
483
486
this . _changeDetectorRef . markForCheck ( ) ;
484
487
} ) ;
485
488
@@ -489,8 +492,17 @@ export class MdInputContainer implements AfterViewInit, AfterContentInit, AfterC
489
492
} ) ;
490
493
}
491
494
492
- // Re-validate when the amount of hints changes.
493
- this . _hintChildren . changes . subscribe ( ( ) => this . _processHints ( ) ) ;
495
+ // Re-validate when the number of hints changes.
496
+ startWith . call ( this . _hintChildren . changes , null ) . subscribe ( ( ) => {
497
+ this . _processHints ( ) ;
498
+ this . _changeDetectorRef . markForCheck ( ) ;
499
+ } ) ;
500
+
501
+ // Update the aria-described by when the number of errors changes.
502
+ startWith . call ( this . _errorChildren . changes , null ) . subscribe ( ( ) => {
503
+ this . _syncAriaDescribedby ( ) ;
504
+ this . _changeDetectorRef . markForCheck ( ) ;
505
+ } ) ;
494
506
}
495
507
496
508
ngAfterContentChecked ( ) {
@@ -522,7 +534,8 @@ export class MdInputContainer implements AfterViewInit, AfterContentInit, AfterC
522
534
/** Determines whether to display hints or errors. */
523
535
_getDisplayedMessages ( ) : 'error' | 'hint' {
524
536
let input = this . _mdInputChild ;
525
- return ( this . _errorChildren . length > 0 && input . _isErrorState ) ? 'error' : 'hint' ;
537
+ return ( this . _errorChildren && this . _errorChildren . length > 0 && input . _isErrorState ) ?
538
+ 'error' : 'hint' ;
526
539
}
527
540
528
541
/**
@@ -574,19 +587,24 @@ export class MdInputContainer implements AfterViewInit, AfterContentInit, AfterC
574
587
private _syncAriaDescribedby ( ) {
575
588
if ( this . _mdInputChild ) {
576
589
let ids : string [ ] = [ ] ;
577
- let startHint = this . _hintChildren ?
578
- this . _hintChildren . find ( hint => hint . align === 'start' ) : null ;
579
- let endHint = this . _hintChildren ?
580
- this . _hintChildren . find ( hint => hint . align === 'end' ) : null ;
581
-
582
- if ( startHint ) {
583
- ids . push ( startHint . id ) ;
584
- } else if ( this . _hintLabel ) {
585
- ids . push ( this . _hintLabelId ) ;
586
- }
587
590
588
- if ( endHint ) {
589
- ids . push ( endHint . id ) ;
591
+ if ( this . _getDisplayedMessages ( ) === 'hint' ) {
592
+ let startHint = this . _hintChildren ?
593
+ this . _hintChildren . find ( hint => hint . align === 'start' ) : null ;
594
+ let endHint = this . _hintChildren ?
595
+ this . _hintChildren . find ( hint => hint . align === 'end' ) : null ;
596
+
597
+ if ( startHint ) {
598
+ ids . push ( startHint . id ) ;
599
+ } else if ( this . _hintLabel ) {
600
+ ids . push ( this . _hintLabelId ) ;
601
+ }
602
+
603
+ if ( endHint ) {
604
+ ids . push ( endHint . id ) ;
605
+ }
606
+ } else if ( this . _errorChildren ) {
607
+ ids = this . _errorChildren . map ( mdError => mdError . id ) ;
590
608
}
591
609
592
610
this . _mdInputChild . ariaDescribedby = ids . join ( ' ' ) ;
0 commit comments