Fecha predeterminada a formato de conversión JSON en la aplicación Angular

Nov 30 2020

Supongamos que un componente (dentro de la aplicación angular) tiene varias formas reactivas que contienen selectores de fechas (estoy usando mat-datepickerde material angular lib) y otras entradas. Después de que un usuario presione el botón "Enviar", envío el valor de los formularios a respaldar (con HttpClient.post). El problema es que los campos del selector de fechas se serializan como "2020-11-18T22:00:00.000Z"(obviamente Date.toJSON()se llama al método) mientras que el backend espera otro formato.

Tenga en cuenta que estoy usando formlylib para construir mis formularios, porque el conjunto de componentes en cada formulario puede variar. Es posible que no esté familiarizado con él, formlypero de todos modos el conjunto de selectores de fechas también puede variar, por lo que no puedo convertir los campos del selector de fechas directamente porque no conozco la lista exacta de campos de fecha en un lugar donde envío el valor de los formularios.

¿Existe una solución elegante a mi problema? ¿No se puede pensar en algo mejor que parchear mono Date.prototype.toJSON()o recorrer los objetos enviados en el servidor, verificar el tipo de campos y cambiar de campo si es un Date? No puedo encontrar una manera de establecer el formato de salida de valor por datepicker, ya sea en material o en forma.

Respuestas

1 ibenjelloun Dec 04 2020 at 15:23

Implementar ControlValueAccessor sería una solución elegante. La idea es crear un componente selector de fecha que tome su formato de fecha como entrada y envíe su formato como salida.

Para eso, solo tiene que crear un nuevo componente al que llamaría MatDatepickerWrapperComponentpara este ejemplo. La plantilla de este componente no sería más que el selector de fecha de material:

<mat-form-field appearance="fill">
  <mat-label>Choose a date</mat-label>
  <input matInput [matDatepicker]="picker" [(ngModel)]="model" (ngModelChange)="modelChange($event)">
  <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
  <mat-datepicker #picker></mat-datepicker>
</mat-form-field>

Desde el lado del componente, tendrá que implementar ControlValueAccessor y hacer las transformaciones que necesita:

writeValue(value: string): void {
    this.model = transformDateFromMyFormatToIso(value);
}
modelChange(value: string) {
    const transformedValue = transformIsoDateToMyFormat(value);
    this.onChange(transformedValue);
  }

Ahora puede agregar el nuevo componente a un formulario de la forma en que habría agregado el original.

Aquí hay un ejemplo de stackblitz en ejecución.

1 RobinDijkhof Dec 04 2020 at 05:26

Intentaría usar un interceptor HTTP. Creo que podrías usar tu interceptor para cambiar todas las fechas del cuerpo a otra cosa.

ingrese la descripción del enlace aquí es un ejemplo de cómo funciona el interceptor. En el ejemplo, se agrega un encabezado. Aquí y aquí hay un ejemplo de modificación del cuerpo.

1 Becike Dec 04 2020 at 15:03

Yo tuve el mismo problema. Podría resolver esto anulando el convertidor de fecha JSON en el componente de la aplicación:

overrideToJSONDate() {
    Date.prototype.toJSON = function () {
      return new Date(this).toLocaleString();
    }
  }

Llamo a esta función una vez en el constructor del componente de la aplicación. Puede aplicar una lógica dentro de la función, pero asegúrese de regresar con la cadena actual.