Формат преобразования даты по умолчанию в JSON в приложении Angular

Nov 30 2020

Предположим, что компонент (внутри приложения angular) имеет несколько реактивных форм, содержащих датпикеры (я использую mat-datepickerиз библиотеки материалов angular) и другие входные данные. После того, как пользователь нажал кнопку «Отправить», я отправляю значение формы в резервную копию (с HttpClient.post). Проблема в том, что поля datepicker сериализуются как "2020-11-18T22:00:00.000Z"(очевидно, Date.toJSON()вызывается метод), в то время как бэкэнд ожидает другого формата.

Обратите внимание, что я использую formlylib для создания своих форм, потому что набор компонентов в каждой форме может отличаться. Возможно, вы не знакомы, formlyно в любом случае набор датпикеров также может отличаться, поэтому я не могу напрямую преобразовывать поля датпикера, потому что я не знаю точный список полей даты в месте, куда я отправляю значение форм.

Есть ли элегантное решение моей проблемы? Не можете придумать что-то лучше, чем исправление обезьяны Date.prototype.toJSON()или перебирать объекты, отправленные на сервер, проверять тип полей и изменять поле, если оно есть Date? Я не могу найти способ установить формат вывода значения с помощью datepicker ни в материале, ни в форме.

Ответы

1 ibenjelloun Dec 04 2020 at 15:23

Реализация ControlValueAccessor была бы элегантным решением. Идея состоит в том, чтобы создать компонент выбора даты, который принимает ваш формат даты в качестве ввода и отправляет ваш формат в качестве вывода.

Для этого вам просто нужно создать новый компонент, который я бы назвал MatDatepickerWrapperComponentдля этого примера. Шаблон этого компонента будет не чем иным, как средством выбора даты материала:

<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>

Со стороны компонентов вам нужно будет реализовать ControlValueAccessor и выполнить необходимые преобразования:

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

Теперь вы можете добавить новый компонент в форму так, как если бы вы добавляли исходный.

Вот пример работающего stackblitz.

1 RobinDijkhof Dec 04 2020 at 05:26

Я бы попробовал использовать перехватчик HTTP. Я думаю, вы могли бы использовать свой перехватчик, чтобы изменить все даты в теле на что-то другое.

введите описание ссылки вот пример того, как работает перехватчик. В примере добавлен заголовок. Вот и вот пример модификации тела.

1 Becike Dec 04 2020 at 15:03

У меня такая же проблема. Я мог бы решить эту проблему, переопределив преобразователь даты JSON в компоненте приложения:

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

Я вызываю эту функцию один раз в конструкторе компонента приложения. Вы можете применить и логику внутри функции, но обязательно верните текущую строку.