新手问个 angular 问题,就是表单数据如何优雅的封装到 model 里 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
helee9199
V2EX    程序员

新手问个 angular 问题,就是表单数据如何优雅的封装到 model 里

  •  
  •   helee9199 24 天前 1382 次点击

    angular 区不太活跃 故移动此区

    因不可抗力原因要求使用 angular20 开始学这个,然后有个问题很困扰 ,就是一般每个表单都会有个对应的 model 页面上会用 formControlName 。 然后我们的 model 字段很多 在 component 里就有很多这种代码

     const tubeData: TubeModel = { commonParams: this.commonParams, tubeInitDate: formatDate(formValue.tubeInitDate, 'yyyy/MM/dd HH:mm'), tubeInsertionDate: formatDate(formValue.tubeInsertionDate, 'yyyy/MM/dd HH:mm'), anticipatedTubeRemovalDate: formatDate(formValue.anticipatedTubeRemovalDate, 'yyyy/MM/dd'), tubeId: formValue.tubeId, tubeName: formValue.tubeName, tubeGroup: formValue.tubeGroup, tubeType: formValue.tubeType, tubeMaterial: formValue.tubeMaterial, tubeProductNumber: formValue.tubeProductNumber, tubeProductNumberOtherValue: formValue.tubeProductNumber || '', innerLength: formValue.innerLength, innerUnit: 'cm', bodyPosition: formValue.bodyPosition, bodyPart: formValue.bodyPart, tubeLength: formValue.tubeLength, tubeUnit: 'cm', seqNumber: formValue.seqNumber === '其他' ? formValue.seqNumberOther : formValue.seqNumber, drainage: formValue.drainage || 0, traits: { color: formValue.color, colorOther: formValue.colorOther || '', nature: formValue.nature, natureOther: formValue.natureOther || '', flavor: formValue.flavor, flavorOther: formValue.flavorOther || '', }, }; 
    以及这种 
     this.form.patchValue({ tubeGroup: tube.tubeGroup, tubeId: tube.tubeId, tubeInitDate: tube.tubeInitDate ? new Date(tube.tubeInitDate) : null, tubeInsertionDate: tube.tubeInsertionDate ? new Date(tube.tubeInsertionDate) : null, anticipatedTubeRemovalDate: tube.anticipatedTubeRemovalDate ? new Date(tube.anticipatedTubeRemovalDate) : null, tubeName: tube.tubeName, tubeType: tube.tubeType, tubeMaterial: tube.tubeMaterial, tubeProductNumber: tube.tubeProductNumber, innerLength: tube.innerLength, bodyPosition: tube.bodyPosition, bodyPart: tube.bodyPart, tubeLength: tube.tubeLength, seqNumber: tube.seqNumber, drainage: tube.drainage, }); 
    还有 init 的时候这种 
     ngOnInit(): void { this.form = this.fb.group({ tubeGroup: [null], tubeId: [null], tubeInitDate: [null], tubeInsertionDate: [null], anticipatedTubeRemovalDate: [null], tubeName: [null], tubeType: [''], tubeMaterial: [null], tubeProductNumber: [null], innerLength: [null], bodyPosition: [null], bodyPart: [''], tubeLength: [null], seqNumber: [null], seqNumberOther: [''], drainage: [null], color: [null], colorOther: [''], flavor: [null], flavorOther: [''], nature: [null], natureOther: [''], }); } 

    我觉得看着很冗余 字段多了一刷一大片 既然有了 model ,有办法简化这部分吗

    17 条回复    2025-11-27 16:40:07 +08:00
    c3de3f21
        1
    c3de3f21  
       24 天前
    signal 和 effect 可以吗,都是比较新的 API?

    model = signal<User>({ name: '', age: 0 });

    form = new FormGroup({
    name: new FormControl(''),
    age: new FormControl(0),
    });


    effect(() => {
    this.form.patchValue(this.model());
    });


    effect(() => {
    this.model.update(m => ({ ...m, ...this.form.value }));
    });
    helee9199
        2
    helee9199  
    OP
       24 天前
    @c3de3f21 你举的例子只有两个属性。但是我想问的是 如果我有 50 个属性,怎么优雅的处理。
    就是想优化 form = new FormGroup({
    name: new FormControl(''),
    age: new FormControl(0),
    });这部分 ,感觉很嗦, 有没有办法实现,因为我是 java ,有没有办法 通过 model 的 class 自动处理这部分?
    shakaraka
        3
    shakaraka  
    PRO
       24 天前
    1 、21 新增了 signal form ,可以尝试。
    2 、标准的写法是:先在 class 里定义好 FormGroup 以及默认值,然后在 init 里或者 http reponse 后进行 patchValue

    我不太懂你的 model 是什么,ng 里没这个概念。首先你得知道 form 的数据结构和后台给你的数据结构是两回事,需要赋值是标准操作
    shakaraka
        4
    shakaraka  
    PRO
       24 天前
    @helee9199 #2 先定义结构,后早操作数据是很正常的编码方式。除非你不在乎类型全程 any ,我有其他方法
    c3de3f21
        5
    c3de3f21  
       24 天前
    @shakaraka #3 他是想类似 vue 的那种,就好像我 new 一个 Person ,然后直接用双绑
    c3de3f21
        6
    c3de3f21  
       24 天前
    ReactiveForm 或者 FormModule ,与 NgModel 选一种,后者更像是你说的那种,可是没有验证
    shakaraka
        7
    shakaraka  
    PRO
       24 天前
    @c3de3f21 #5 只有 21 版的 signal form 体验会好很多。旧版的就按照原始的标准做法做就行了,没 vue 那种
    helee9199
        8
    helee9199  
    OP
       24 天前
    @shakaraka 我去 怎么这么快 上周还是 20 怎么就 21 了。。。
    helee9199
        9
    helee9199  
    OP
       24 天前
    @shakaraka 就是例如我后台要存资料 这笔资料有 50 个属性 ,前端我也会写一个 50 个属性的 interface 或者 class 也就是我所说的 model 。
    然后保存数据的时候封装成这个 model 传给后台
    目前页面上会写 formCOntrolName='beanName'
    然后这种做法就会出现我主楼里那种罗嗦的写法。
    shakaraka
        10
    shakaraka  
    PRO
       24 天前
    @helee9199 #8 很久官方就预告 20 号出了。你没关注
    shakaraka
        11
    shakaraka  
    PRO
       24 天前
    @helee9199 #9 首先你写 java 肯定知道 DTO 、VO 这些鬼东西。

    先抛开 ng 的 FormGroup ,换个角度想,后端给你定义的数据类型,只是交换数据而已,彼此沟通所需要的内容而已。

    但是你页面上,还有控制你页面的属性、字段等,这些后端是不需要的,所以在页面上是会有自己的一套数据结构。

    你不能想当然把交换数据的结构当做是你页面上要用到的结构。

    一个一个转换、赋值是最稳妥、最一目了然的做法。
    helee9199
        12
    helee9199  
    OP
       24 天前
    @shakaraka 啊 一个一个写转换赋值那这也太蠢了吧,init 的时候要做一遍 数据提交的时候又要做一遍, 真的没有什么方法或者组件能实现 页面上的 beanname 和 model 对应上了就能自动封装的操作吗?
    也就是 springmvc 那种模式。form 里的 name 和 model 的 beanname 对应上 自动封装数据。
    shakaraka
        13
    shakaraka  
    PRO
       24 天前   1
    @helee9199 #12

    并不会。而且现在 21 版本有了 signal form ,总体来说会好用很多。



    你可以看看这个视频,不管用不用 signal form ,还是 vue 那种,我上面说的逻辑还是不变的。

    你始终需要先定义,再使用,这个是个最佳实践方式。特别像是在 vue2 的时候,你动态给 data 赋值,新手还出现很多赋值了,页面没反应,又或者是表单找不到 data 里的数据了,等等。

    https://www.bilibili.com/video/BV1Nys4zvEmr
    helee9199
        14
    helee9199  
    OP
       24 天前   1
    @shakaraka 好吧,这个问题纠结了三四天了,因为就是想找个办法解决这个痛点,工作进度一直卡着在。
    也能是 java 后端的僵化思维吧,带着 java 的思维搞 angular 。
    你这个视频确实是有些启发。既然是这样 还是老老实实的写吧。
    感谢了~
    nzbin
        15
    nzbin  
       23 天前   1
    先不用考虑 signal form ,对于小白来说,你的需求首选就是 Reactive Form

    第一:50 个字段不算多,一般就是初始化定义一次,用的就是 this.form = this.fb.group
    第二:提交的时候直接用 this.form.value (或者 this.form.rawValue ,禁用的字段也能取出) 获得表单值就可以,不需要额外处理了(特殊情况可能会对某几个字段处理)
    第三:想要做到第二点可能需要自定义表单控件,不过大部分组件库的大部分组件应该都满足,考虑到业务的多样性,很多情况是满足不了的,比如有一个布尔类型的字段,前端组件库处理都是 true 或者 false ,但是后端要求传值是 1 和 0 ,那直接绑定就不行了,提交的时候肯定要后处理,但是你可以定义一个 <app-checkbox /> 的组件,内部做转换,form.value 的值不用后处理了
    第四:patchValue(object) 就行啊,也不用一个一个字段写出来,后端的返回数据和提交数据应该都一样吧,特殊不一样的字段单独处理就行

    当然,对于新手来说,不用考虑第三点,先用 form.value 取值,最后需要处理的字段单独处理就行了
    helee9199
        16
    helee9199  
    OP
       21 天前
    @nzbin 嗯嗯 主要是 java 思维带过来了,这两天稍微适应些了
    nzbin
        17
    nzbin  
       21 天前
    @helee9199 #16
    其实用 java 思维写 Angular 是完全没问题的,比如你定义一个 class 来处理 model 肯定可以,但是要转换 class 才能传给 this.fb.group ,有 OOP 的编码经验上手 Angular 会更容易
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1289 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 32ms UTC 17:09 PVG 01:09 LAX 09:09 JFK 12:09
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86