1

I have a date_of_birth field with an epoch string saved to it. I wanted to use angular material date picker to alter the date which is possible by converting it through

//convert matDatepicker timestamp format to epoch and save
var newDOB = new Date(privateUser.date_of_birth).getTime().toString();
privateUser.date_of_birth = newDOB;

before storing it into the db, however when trying to display it within the date selection as the default date, I'm not very sure how to revert it.

this is the current code i have

<div *ngIf="(userPrivate$ | async) as userPrivate">
  <form (ngSubmit)="updateUser(user, userPrivate)">
    <mat-form-field >
      <input matInput type="text" [(ngModel)]="user.username" name="username" placeholder="Username">
    </mat-form-field >
    <mat-form-field >
      <input matInput [matDatepicker]="dp" placeholder="Date of Birth"   [(ngModel)]="userPrivate.date_of_birth" name="date_of_birth">
      <mat-datepicker-toggle matSuffix [for]="dp"></mat-datepicker-toggle>
      <mat-datepicker #dp >
      </mat-datepicker>
    </mat-form-field>
  </form>
</div>

and when i try adding

<mat-form-field >
  <input matInput [matDatepicker]="dp" placeholder="Date of Birth" [formControl]="userPrivate.date_of_birth"  [(ngModel)]="userPrivate.date_of_birth" name="date_of_birth">
  <mat-datepicker-toggle matSuffix [for]="dp"></mat-datepicker-toggle>
  <mat-datepicker #dp >
  </mat-datepicker>
</mat-form-field>

I will get an error as it will not be able to read the value, it also cant take in whatever it was I was trying to do by adding the function to convert it from epoch.

<mat-form-field >
  <input matInput [matDatepicker]="dp" placeholder="Date of Birth" [formControl]="getDate(userPrivate.date_of_birth)"  [(ngModel)]="userPrivate.date_of_birth" name="date_of_birth">
  <mat-datepicker-toggle matSuffix [for]="dp"></mat-datepicker-toggle>
  <mat-datepicker #dp >
  </mat-datepicker>
</mat-form-field>

where getDate(date) function

getDate(date){
  // convert Epoch time to timestamp format
  var newDate= new Date(date).getTime();
  return newDate;
}

How am I suppose to be approaching this so that I can have my date input to display the date_of_birth value as a default?

Monomoni
  • 415
  • 2
  • 4
  • 19

1 Answers1

0

When you have a different date format in your date picker compared to your own data structure, in general, you have two choices: 1) somehow tell the datePicker component to convert its data structure to your ones, this is usually done via passing an adapter class 2) let the datePicker to pass its own data format to the form or model, and only convert manually whenever you are posting the form, or setting the form value.

Using an adapter

Actually the material datepicker does give you the possiblity to provide an adapter, the usage is pretty well described at https://material.angular.io/components/datepicker/overview

Converting manually

When converting manually, you have to do the conversion from your data structure to the datepickers one to set the initial value and when a parent component updates the form value. And you have to do the reverse direction conversion whenever you want to save the data from the form.

So you don't have to add the conversion method to the template in any way, do the conversion in the submit method. What is definitely wrong in your example is that the [formControl] expects an angular form control, not a value (the date itself in this case).

Personally, I would go with the adapter solution, because that way the converting logic is not scattered around, but focused to a specific class, which is also easier to test.

A completely unrelated note

In general, try not to call methods in value bindings, eg.

<input matInput [formControl]="getDate(userPrivate.date_of_birth)" > (some attributes omitted for brevity)

Those methods are called upon every change detection (which can happen fairly often, especially if you don't use ChangeDetectionStrategy.onPush), so the conversion is done upon every change detection, even when the source value hasn't changed.

It is very easy to hide complex computations in these bound methods, which might considerably slow down your app.

Instead, do the calculation only when the source value changes, store the result in a field of the component, bind that field in the template.

Alex Biro
  • 1,069
  • 1
  • 14
  • 27