Angular中如何将textarea输入转为数组?表单提交数组变字符串问题
问题
在Angular表单中使用textarea,将string[]作为FormControl的类型。在ngModelChange事件中提取输入的邮箱地址并赋值给数组,但提交表单时数组却被转为字符串值,请问这种实现方式是否正确?
相关代码:
public emailList: string[] = []; public form: FormGroup = new FormGroup({}); public ngOnInit(): void { this.form = new FormGroup({ sendMeACopy: new FormControl(false, []), emailAddressesGroup: new FormControl(this.emailList, [ Validators.pattern(/^([\w+-.%]+@[\w-.]+\.[A-Za-z]{2,4},?\s?)+$/), ]), }); } public extractEmailList(e: any): void { this.emailList = []; if (this.generateMonthlyProductionReportForm.valid) { let emails = e.replace(/\s/g, "").split(","); emails.forEach((email: any) => { if (email && email.length > 0) { this.emailList.push(email); } }); } } public report() { if (this.form.invalid) { for (const control of Object.keys( this.form.controls )) { this.form.controls[ control ].markAsTouched(); } return; } console.log(this.form.value); }
<form [formGroup]="form"> <div class="container"> <div> <div>Recipient</div> <div> <ejs-checkbox formControlName="sendMeACopy" name="send me a copy" label="Send me a copy" > </ejs-checkbox> </div> <div> <textarea (ngModelChange)="extractEmailList($event)" formControlName="emailAddressesGroup" id="emailAddresses" name="Email Address Input" placeholder="Use a comma to separate email addresses." ></textarea> <div *ngIf=" form.controls[ 'emailAddressesGroup' ].hasError('pattern') && form.controls[ 'emailAddressesGroup' ].dirty " class="e-error" > Please enter comma separated list of valid email addresses. </div> </div> </div> </div> <button (click)="report()" class="btn btn-primary" [disabled]="!form.valid" type="button" > Submit </button> </form>
表单提交输出:
- 初始状态:
{"emailAddressesGroup": [], "sendMeACopy": false}
- 输入值后:
{"emailAddressesGroup": "asds@sfg.gh, sdf@sfdf.hj", "sendMeACopy": false}
问题分析与解决方案
你的实现方式存在核心问题,同时还有几处细节错误:
- 表单变量引用错误:
extractEmailList里用了不存在的generateMonthlyProductionReportForm,实际应该用this.form,导致邮箱解析逻辑从未执行。 - 控件值未同步:textarea的输入本质是字符串,FormControl会自动同步这个字符串到控件值中,你只更新了
emailList变量,但没有修改FormControl的实际值,所以提交时还是原始字符串。 - 校验逻辑与存储类型不匹配:你用校验字符串的正则来校验数组类型的控件值,逻辑上不兼容。
修正方案(两种可选)
方案1:保持控件存字符串,提交时转数组(推荐,贴合textarea特性)
这种方式最简单,利用textarea原生的字符串输入,提交时再解析为数组,保留原有校验逻辑:
public emailList: string[] = []; public form: FormGroup = new FormGroup({}); public ngOnInit(): void { this.form = new FormGroup({ sendMeACopy: new FormControl(false, []), emailAddressesGroup: new FormControl('', [ Validators.pattern(/^([\w+-.%]+@[\w-.]+\.[A-Za-z]{2,4},?\s?)+$/), ]), }); } // 实时解析邮箱列表(可选,用于展示或其他逻辑) public extractEmailList(e: string): void { this.emailList = []; if (e) { const emails = e.replace(/\s/g, "").split(","); this.emailList = emails.filter(email => email.trim().length > 0); } } public report() { if (this.form.invalid) { Object.values(this.form.controls).forEach(control => control.markAsTouched()); return; } // 提交时将字符串转为数组 const submitValue = { ...this.form.value, emailAddressesGroup: this.emailList }; console.log(submitValue); }
方案2:让控件直接存储数组(自定义同步逻辑)
如果需要表单生命周期内始终操作数组,可手动同步控件值,并调整校验逻辑:
public emailList: string[] = []; public form: FormGroup = new FormGroup({}); public ngOnInit(): void { this.form = new FormGroup({ sendMeACopy: new FormControl(false, []), emailAddressesGroup: new FormControl([], [ // 自定义校验:检查数组中每个邮箱是否合法 (control) => { const emails = control.value as string[]; const emailRegex = /^[\w+-.%]+@[\w-.]+\.[A-Za-z]{2,4}$/; const invalidEmails = emails.filter(email => !emailRegex.test(email)); return invalidEmails.length > 0 ? { invalidEmails: true } : null; } ]), }); } public extractEmailList(e: string): void { this.emailList = []; if (e) { const emails = e.replace(/\s/g, "").split(","); this.emailList = emails.filter(email => email.trim().length > 0); } // 同步更新FormControl的值为数组 this.form.get('emailAddressesGroup')?.setValue(this.emailList); } public report() { if (this.form.invalid) { Object.values(this.form.controls).forEach(control => control.markAsTouched()); return; } console.log(this.form.value); }
对应HTML调整错误提示(方案2用):
<div *ngIf=" form.controls['emailAddressesGroup'].hasError('invalidEmails') && form.controls['emailAddressesGroup'].dirty " class="e-error" > 请输入有效的邮箱地址,用逗号分隔。 </div>
内容的提问来源于stack exchange,提问作者tangel
相关产品推荐
相关产品推荐

