構築しているアプリケーションの場合、APIからデータを取得し、その応答を使用してフォーム値を直接設定しています。そのために、私はリアクティブフォームモジュールを使用しています。 APIから取得するオブジェクトと一致するようにフォームを作成しました。問題は、一部のフィールドがオブジェクト(FormGroup)であると想定されているが、空の場合はNULLになることです。これにより、「未定義またはnullをオブジェクトに変換できません」というエラーが発生します。
FormGroupインスタンス:
note: this.formBuilder.group({
turnbook_file: [''],
note: [''],
additional_files: ['']
});
APIからの応答
note: NULL
私の考えでは、ORステートメントなど、FormGroupを次のように定義する場所に配置することは可能かもしれません。
note: this.formBuilder.group({
turnbook_file: [''],
note: [''],
additional_files: ['']
} | NULL);
Lodash pickByメソッドを使用して、API応答を使用する前にラップしてみることができます。
import * as _ from 'lodash';
...
//fetch data from API
note.patchValue(
_.pickBy(apiResponse)
);
...
短い答え:Angular FormsAPIの現在の実装では-FormGroup
とnull
またはundefined
の値。
理由:すべてのシナリオでnew FormGroup(), formBuilder.group(), patchValue()
などのメソッドObject.keys()
が呼び出され、エラーがスローされます_Cannot convert undefined or null to object
_を引数として渡す場合は_null/undefined
_(JS仕様による)。
証明:
FormBuilder
のgroup()
メソッド( ソースコードリンク ):
_ group(controlsConfig: {[key: string]: any}, ...) {
const controls = this._reduceControls(controlsConfig);
...
}
_reduceControls(controlsConfig: {[k: string]: any}) {
Object.keys(controlsConfig).forEach(...);
...
}
_
FormGroup
's patchValue
( ソースコードリンク ):
_patchValue(value: {[key: string]: any}, ...) {
Object.keys(value).forEach(...);
...
}
_
回避策:
{}
_を送信するようにします。FormGroup
クラスを拡張し、_constructor/patchValue
_をオーバーライドできる新しいクラスを作成します。引数が_null/undefined
_であるかどうかを確認します-代わりに空のオブジェクトを使用します。FormBuilder
サービスを拡張し、group
メソッドをオーバーライドできる独自のシングルトンサービスを作成します(アプリ内のあらゆる場所で使用します)(前のポイントを参照)。フォームとコントロールを定義する場合は、それに値を渡す必要があるため、応答がnullの場合は、次のようにフォームコントロールの値を設定します。
note.setValue({
'turnbook_file': data.turnbook_file == null ? "": data.turnbook_file,
'note: ,data.note == null ? "": data.note,
'additional_files': data.additional_files == null ? "":
data.additional_files,
})
このようにフォームを定義できます
note =new FormGroup({
'turnbook_file': new FormControl(null),
'note: new FormControl(null),
'additional_files': new FormControl(null)
})
2つの解決策が思い浮かびます
@NgModule({...})
export class AppModule {
constructor() {
const builtInFunction = FormGroup.prototype.patchValue;
FormGroup.prototype.patchValue = function (value, options?) {
builtInFunction.call(this, value || {}, options);
}
}
}
import {FormGroup, ValidatorFn, AbstractControlOptions, AsyncValidatorFn} from '@angular/forms';
export class MyFormGroup extends FormGroup {
constructor(
controls: {[key: string]: any},
validatorOrOpts?: ValidatorFn | ValidatorFn[] | AbstractControlOptions | null,
asyncValidator?: AsyncValidatorFn | AsyncValidatorFn[] | null
) {
super(controls, validatorOrOpts, asyncValidator);
}
patchValue(value: {[key: string]: any}, options: {onlySelf?: boolean, emitEvent?: boolean} = {}) {
super.patchValue(value || {}, options);
}
}
フォームにパッチを適用する前に、これらの値を簡単に除外できます
const obj = {
foo: "bar",
bar: null,
cat: undefined,
dog: "bark"
}
const truthy = Object.keys(obj).filter(item => obj[item] != undefined || obj[item] != null );
const newObj = {};
truthy.forEach(item =>Object.assign(newObj, { [item]: obj[item]}));
console.log(newObj) // { foo: "bar", dog: "bark" }
偽の値を除外したら、それを使用してフォームにパッチを適用します