Search code examples
angulardatepickerangular-materialngmodelangularfire5

matDatePicker with angular cloud firestore and [(ngModel)]


With Real Time Database, I used the angular material matDatePicker to save date news.

Since I have moved on with firestore collection, when I call the saved date in an angular service, it shows it as an object

  "date": {
     "seconds": 1529445600,
     "nanoseconds": 0
  },

and I can't use it with [(ngModel)]. It looks like it's no longer a string so the matDatepicker matInput doesn't recognize it anymore.

So how should I bind the matDatepicker value in to the ngModel of my view?

Template:

    <mat-form-field>
      <input matInput [matDatepicker]="picker" 
        placeholder="Date" required readonly
        [(ngModel)]="news.date"
            (ngModelChange)="updateField(news,'date',news.date)">
      <mat-datepicker-toggle matSuffix type="button" [for]="picker"></mat-datepicker-toggle>
      <mat-datepicker #picker></mat-datepicker>
    </mat-form-field>

Service:

getNewsWithKey(key: string): Observable<SingleNews> {
const newsPath = `news/${key}`;
this.news = this.afs.doc<any>(newsPath)
  .snapshotChanges().map(action => {
    const $key = action.payload.id;
    const data = { $key, ...action.payload.data() }
    return data;
  });
return this.news}

Solution

  • It appears that the object that is being saved is of type firebase.firestore.Timestamp. This change was added in Firebase JS SDK v4.13.0, where JavaScript Date objects will be saved of type Timestamp.

    In the Timestamp class, there's a method called toDate, which converts the Timestamp to a JavaScript Date object.

    Here's what you can do:

    • You can try assigning a temporary object with the converted Timestamp and whatever data is saved remotely.

      getNewsWithKey(key: string): Observable<SingleNews> {
        const newsPath = `news/${key}`;
        this.news = this.afs.doc<any>(newsPath)
          .snapshotChanges().map(action => {
            const $key = action.payload.id;
            const data = Object.assign(action.payload.data(), { date: action.payload.data().date.toDate(), $key: action.payload.id });
            return data;
          });
        return this.news;
      }