最近、角張ったフォームを扱っていると、4層構造のフォームがありました。そして、次のように多くの要素が動的に生成されます。
this.validateForm=this.fb.group({
storeId: ["test12"],
storeNameKey:[''],
config:this.fb.group({
tableSize:this.fb.group({
toggle:[false],
groupSize:this.fb.array([
this.fb.group({
cate:['indoor'],
title_en:[''],
title_zh:[''],
tableSize:this.fb.array([
this.fb.group({
size: [""],
desc_en:["small"],
desc_zh: ["小桌"],
number:['A02'],
preTitle: ["C"],
maxPerson: [8],
minPerson: [5],
alias: "S",
}),
])
}),
this.fb.group({
cate:['outdoor'],
title_en:[''],
title_zh:[''],
tableSize:this.fb.array([
this.fb.group({
size: ["small"],
desc_en:["Small"],
desc_zh: ["小桌"],
number:['A02'],
preTitle: ["C"],
maxPerson: [8],
minPerson: [5],
alias: "S",
}),
])
}),
]),
}),
hasMoreTableSize:['false'],
geoFancing:this.fb.group({
// isOpenGeo:['true'],
range:[100]
}),
dynamicQRCode:this.fb.group({
refreshEx:[2]
}),
isLogin:[false],
isShowBlockList:[false]
}),
})
そのインターフェイスは次のように動作します。
、編集状態でバックエンドによって返されたデータ構造に従ってエコーする方法について説明します。angular の formbuilder オブジェクトには、setValue と patchValue という 2 つのメソッドが用意されています。これら 2 つの方法は 1 レベルのオブジェクトに対してのみ有効であり、複数レベルのネストされたデータ構造に対しては有効ではありません。いろいろ調べた結果、この方法で解決できることが分かりました。
まずバックエンドのデータ構造をシミュレートします。
const formdata={
storeId:"disneycart",
storeNameKey:"123",
config:{
tableSize:{
toggle:true,
groupSize:[
{
cate:"indoor",
title_en:'',
title_zh:'',
tableSize:[
{
alias: "S",
desc_en: "small",
desc_zh: "小4桌",
maxPerson: 4,
minPerson: 1,
number: "A01",
preTitle: "A",
size: "small"
},
{
alias: "m",
desc_en: "middl",
desc_zh: "中桌",
maxPerson: 6,
minPerson: 4,
number: "b01",
preTitle: "B",
size: "middle"
},
{
alias: "L",
desc_en: "large",
desc_zh: "中桌",
maxPerson: 6,
minPerson: 4,
number: "b01",
preTitle: "c",
size: "large"
},
]
},
{
cate:"outdoor",
title_en:'',
title_zh:'',
tableSize:[
{
alias: "S",
desc_en: "small",
desc_zh: "小4桌",
maxPerson: 4,
minPerson: 1,
number: "A01",
preTitle: "A",
size: "small"
},
{
alias: "m",
desc_en: "middl",
desc_zh: "中桌",
maxPerson: 6,
minPerson: 4,
number: "b01",
preTitle: "B",
size: "middle"
}
]
}
]
},
dynamicQRCode:{
refreshEx:200
},
geoFancing:{
range:200.,
// isOpenGeo:false
},
hasMoreTableSize:true,
isLogin:true,
isShowBlockList:true
}
}
ページの初期化時に、エコーのためにフロントエンドにデータを返すことをシミュレートします。
ngAfterViewInit(){
setTimeout(()=>{
this.repatchForm(formdata)
console.log("settimeout---后", this.validateForm)
},2000)
}
repatchForm(responseData:any){
let arr2=this.resetAndGetGroupSize(responseData)
console.log("settimeout---前", this.validateForm)
this.validateForm.patchValue({
storeId: responseData.storeId,
storeNameKey: responseData.storeNameKey,
config: {
tableSize: {
toggle: responseData.config.tableSize.toggle,
groupSize: arr2
},
hasMoreTableSize: responseData.config.hasMoreTableSize,
geoFancing: {
range: responseData.config.geoFancing.range
},
dynamicQRCode: {
refreshEx: responseData.config.dynamicQRCode.refreshEx
},
isLogin:responseData.config.isLogin,
isShowBlockList:responseData.config.isShowBlockList
}
});
}
これがコアであることに注意してください。新しい formGroup オブジェクトを作成し、その form オブジェクトを使用して内部の元のグループを削除します。
最後に、patchValue を介して再コピーします。ここでは、元の groupSize オブジェクトをクリアし、最後に新しいバックエンド データを走査することで新しい formArray オブジェクトを生成し、最後にこの新しい formArray オブジェクトを patchValue を通じて再割り当てして有効にすることに特に注意してください。
//处理会显时table列表数据
resetAndGetGroupSize(resData:any){
let arr=resData?.config?.tableSize?.groupSize.map((group: any) => {
return this.fb.group({
cate: group.cate,
title_en: group.title_en,
title_zh: group.title_zh,
tableSize: this.fb.array(group.tableSize.map((table: any) => {
return this.fb.group({
size: table.size,
desc_en: table.desc_en,
desc_zh: table.desc_zh,
number: table.number,
preTitle: table.preTitle,
maxPerson: table.maxPerson,
minPerson: table.minPerson,
alias: table.alias
});
}))
})
})
this.groupSize.clear()
arr.forEach((item:FormGroup)=>{
this.groupSize.push(item)
})
let arr2=arr.map((item:FormGroup)=>{
return item.value
})
return arr2
}