angular中多层嵌套结构的表单如何处理回显问题

最近在处理angular表单时,有一个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两个方法。这两个方法只对一层对象有效,对于多层嵌套的数据结构,无法生效。经过摸索,发现可以这种方式解决。

首先模拟后端数据结构:

复制代码
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对象,然后通过表单对象把原本里面的group干掉

最后通过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
  }
相关推荐
不会敲代码1几秒前
我花了三天时间,终于把 Cookie、XSS、CSRF 和浏览器存储给整明白了
javascript·面试
IT_陈寒5 分钟前
Vite这个坑我帮你踩了,动态导入居然这样才生效
前端·人工智能·后端
贩卖黄昏的熊7 分钟前
flex 布局快速梳理
开发语言·javascript·css3·html5
swipe9 分钟前
Mem0 x Agent 实战系列:分层记忆 + 三路召回,搭建真正可用的长期记忆层
前端·javascript·面试
鹤鸣的日常16 分钟前
前端运行时动态环境变量方案
前端·react.js·docker·前端框架·vue·gitlab
Lee川17 分钟前
Event Loop 面试通关:从原理到口述再到实战
前端·面试
kyriewen37 分钟前
手写 call、apply、bind:从原理到实现,附 3 个最容易忽略的边界情况
前端·javascript·面试
用户21816970493043 分钟前
swift (三) 枚举 结构体 类
前端
胡萝卜术1 小时前
从内存视角重新认识 JavaScript 数据类型:一份深度学习笔记
前端·javascript·面试
IVEN_1 小时前
记一次诡异的前端白屏故障:Nginx Proxy Cache 内存缓存"幽灵"事件
前端·nginx