Fecha predeterminada a formato de conversión JSON en la aplicación Angular
Supongamos que un componente (dentro de la aplicación angular) tiene varias formas reactivas que contienen selectores de fechas (estoy usando mat-datepicker
de 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 formly
lib para construir mis formularios, porque el conjunto de componentes en cada formulario puede variar. Es posible que no esté familiarizado con él, formly
pero 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
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 MatDatepickerWrapperComponent
para 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.
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.
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.