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 ,有办法简化这部分吗
1
c3de3f21 1 天前
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 })); }); |
2
helee9199 OP @c3de3f21 你举的例子只有两个属性。但是我想问的是 如果我有 50 个属性,怎么优雅的处理。
就是想优化 form = new FormGroup({ name: new FormControl(''), age: new FormControl(0), });这部分 ,感觉很啰嗦, 有没有办法实现,因为我是 java ,有没有办法 通过 model 的 class 自动处理这部分? |
3
shakaraka PRO 1 、21 新增了 signal form ,可以尝试。
2 、标准的写法是:先在 class 里定义好 FormGroup 以及默认值,然后在 init 里或者 http reponse 后进行 patchValue 我不太懂你的 model 是什么,ng 里没这个概念。首先你得知道 form 的数据结构和后台给你的数据结构是两回事,需要赋值是标准操作 |
6
c3de3f21 1 天前
ReactiveForm 或者 FormModule ,与 NgModel 选一种,后者更像是你说的那种,可是没有验证
|
9
helee9199 OP @shakaraka 就是例如我后台要存资料 这笔资料有 50 个属性 ,前端我也会写一个 50 个属性的 interface 或者 class 也就是我所说的 model 。
然后保存数据的时候封装成这个 model 传给后台 目前页面上会写 formControlName='beanName' 然后这种做法就会出现我主楼里那种罗嗦的写法。 |
11
shakaraka PRO @helee9199 #9 首先你写 java 肯定知道 DTO 、VO 这些鬼东西。
先抛开 ng 的 FormGroup ,换个角度想,后端给你定义的数据类型,只是交换数据而已,彼此沟通所需要的内容而已。 但是你页面上,还有控制你页面的属性、字段等,这些后端是不需要的,所以在页面上是会有自己的一套数据结构。 你不能想当然把交换数据的结构当做是你页面上要用到的结构。 一个一个转换、赋值是最稳妥、最一目了然的做法。 |
12
helee9199 OP @shakaraka 啊 一个一个写转换赋值那这也太蠢了吧,init 的时候要做一遍 数据提交的时候又要做一遍, 真的没有什么方法或者组件能实现 页面上的 beanname 和 model 对应上了就能自动封装的操作吗?
也就是 springmvc 那种模式。form 里的 name 和 model 的 beanname 对应上 自动封装数据。 |
13
shakaraka PRO @helee9199 #12
并不会。而且现在 21 版本有了 signal form ,总体来说会好用很多。 你可以看看这个视频,不管用不用 signal form ,还是 vue 那种,我上面说的逻辑还是不变的。 你始终需要先定义,再使用,这个是个最佳实践方式。特别像是在 vue2 的时候,你动态给 data 赋值,新手还出现很多赋值了,页面没反应,又或者是表单找不到 data 里的数据了,等等。 https://www.bilibili.com/video/BV1Nys4zvEmr |
14
helee9199 OP @shakaraka 好吧,这个问题纠结了三四天了,因为就是想找个办法解决这个痛点,工作进度一直卡着在。
也能是 java 后端的僵化思维吧,带着 java 的思维搞 angular 。 你这个视频确实是有些启发。既然是这样 还是老老实实的写吧。 感谢了~ |
15
nzbin 14 小时 57 分钟前
先不用考虑 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 取值,最后需要处理的字段单独处理就行了 |