Angularアプリのデフォルトの日付からJSONへの変換形式

Nov 30 2020

日付ピッカー(mat-datepickerAngular Material libから使用しています)とその他の入力を含むいくつかのリアクティブフォームを持つコンポーネント(Angularアプリ内)を想定します。ユーザーが「送信」ボタンを押した後、フォームの値をbacked(with HttpClient.post)に送信します。問題は、バックエンドが他の形式を予期しているのに、日付ピッカーフィールドが"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();
    }
  }

この関数は、アプリコンポーネントのコンストラクターで一度呼び出します。関数内でロジックを適用できますが、必ず現在の文字列で戻るようにしてください。