9

This issue faced when using mat-datepicker inside *ngFor.

mat-datepicker requires a template reference variable #test in order to bind to the input.
Is there a direct way to take reference variables when using inside *ngFor, in general? I couldn't find a way.

Simple working example without *ngFor

<mat-form-field>
  <input matInput [matDatepicker]="test" placeholder="Enter Date" [(ngModel)]="someDate" name="someDate">
  <mat-datepicker-toggle matSuffix [for]="test"></mat-datepicker-toggle>
  <mat-datepicker #test></mat-datepicker>
</mat-form-field>

But since template reference variables must be unique for the whole template, you can't directly use the mat-datepicker for scenario when the above block is repeated inside an *ngFor, test wouldn't be unique.

Any pointers will be helpful.

bitscanbyte
  • 650
  • 8
  • 14

2 Answers2

14

You could add an index variable to your ngFor and assign the value of that index as an identifier for you datepicker. You could also make a public array of values inside the component that have a meaning like ["dtPickerOne", "dtPickerTwo"] and use those as values.

<div *ngFor="let t of test; let i = index;">
         <input matInput [matDatepicker]="i" placeholder="Choose a date" [attr.id]="dtPicker + i"
         [formControl]="dateFrom">
         <mat-datepicker-toggle matSuffix [for]="i"></mat-datepicker-toggle>
         <mat-datepicker #i></mat-datepicker>   
    </div>
theriddle2
  • 398
  • 3
  • 9
  • 1
    This seems to work, but it causes weird behaviour if you try to use `i` somewhere else in the template, for example in string interpolation, you don't get `1 or 2 or 3`, you get `[object object]`. For this I had to use another `let j=index`. It would help if there was a better way to use reference variables in template driven forms inside `*ngFor`. Your 2nd approach seems suited for rather Reactive forms. – bitscanbyte Mar 23 '18 at 15:43
  • 1
    As referenced by @bitscanbyte, you may have to use multiple `let x=index` statements. If you are using reactive forms with multiple date pickers, you can use `let i=index` and `[formGroupName]="i"`, and `let j=index` for the first datepicker as shown in the answer (except using j). Then for more datepickers in the same form group, add another `let k=index` and then use k as the template reference variable, and so on. – Tim Jul 11 '18 at 17:22
  • Hi @theriddle2 I have a question which is been unanswered on date picker can you try on it please the link is https://stackoverflow.com/questions/64278503/highlight-a-particular-week-of-a-particular-month-in-angular-material-datepicker/64278675?noredirect=1#comment113734927_64278675 – kushal Baldev Oct 14 '20 at 21:53
14

I would like to point out that you can use underscore "_" as a separator if you would like to give it a more meaningful name.

Here is a working example with two way model binding.

<div *ngFor="let patient of patients; let i = index;">
  <input matInput [matDatepicker]="patientDueDate_i" placeholder="Due date" 
    [(ngModel)]="patient.dueDate">
   <mat-datepicker-toggle matSuffix [for]="patientDueDate_i"></mat-datepicker-toggle>
   <mat-datepicker #patientDueDate_i></mat-datepicker>   
</div>
Talnaci Sergiu Vlad
  • 922
  • 1
  • 10
  • 17