Angular中如何跨组件导入组件并复用Formly表单字段
问题根因
TS抛出'CopyScheduleFromSiteComponent' is declared but its value is never read的直接原因是:你仅在SiteScheduleComponent顶部写了组件导入语句,但既没有在模板中使用该组件的选择器,也没有在业务逻辑中引用这个类,TS检测到导入的变量未被使用就会触发该报错。
除此之外当前实现还有逻辑断层问题:两个组件各自维护独立的FormGroup、Formly字段配置和数据模型,完全没有做关联,就算消除了TS报错,子组件的表单字段也不会接入父组件的Formly体系,选值、禁用状态、校验逻辑都不会和父表单同步。
可行解决方案
根据字段复用需求二选一即可:
方案1:直接合并字段配置(单场景使用优先选,零额外成本)
如果这个复制站点的选择字段只在SiteScheduleComponent里用,完全没必要抽成独立组件,直接把子组件里的select字段配置合并到父组件的Formly fields数组里即可,TS报错会直接消失:
- 删掉SiteScheduleComponent顶部没用的
CopyScheduleFromSiteComponent导入语句。 - 把子组件里定义的siteScheduleControl select字段,放到SiteScheduleComponent的fields数组里,和现有Copy按钮放在同一个fieldGroup下,调整className让两个控件并排:
fields: FormlyFieldConfig[] = [ { fieldGroupClassName: 'row', fieldGroup: [ // 新增:原属于子组件的站点选择下拉 { wrappers: ['form-field'], className: 'col-6', key: 'siteScheduleControl', type: 'select', templateOptions: { label: 'Copy Schedule from Site', options: this.approvedSites, labelProp: 'text', }, expressionProperties: { 'templateOptions.disabled': (): boolean => this.siteSubmissionModel.disableControls }, }, // 原有Copy按钮配置保留,className调整为col-6和下拉并排 { wrappers: ['form-field'], className: 'col-6 mt-small', type: 'button', templateOptions: { text: 'Copy', matIcon: 'file_copy', onClick: (): void => { if (this.model.monthsOfOperation && (this.model.monthsOfOperation.fromDate || this.model.monthsOfOperation.toDate)) { this.showOverwriteWarningModal().subscribe((confirmed) => { if (confirmed) this.copySchedule(); }); } else { this.copySchedule(); } }, }, expressionProperties: { 'templateOptions.disabled': (): boolean => !this.model.siteScheduleControl || this.siteSubmissionModel.disableControls }, }, ], }, // 后续原有的Months of Operation等字段配置全部保留不变 ]
这个方案下select字段直接属于父组件Formly表单,选值会自动同步到model.siteScheduleControl,之前写好的按钮禁用、复制逻辑不需要任何修改就能正常运行,维护成本最低。
方案2:保留独立子组件(适合多场景复用字段的情况)
如果后续需要在其他页面复用这个站点选择下拉字段,就按以下步骤改造,打通父子组件的Formly关联:
- 先在使用该组件的所属NgModule的
declarations数组中声明CopyScheduleFromSiteComponent,否则组件无法被模板识别。 - 改造子组件,不要在内部新建独立的FormGroup,通过输入属性接收父组件的表单实例,把字段直接注册到父表单上:
// CopyScheduleFromSiteComponent 改造后代码 import { Component, Input, OnInit } from '@angular/core'; import { FormGroup } from '@angular/forms'; import { FormlyFieldConfig, FormlyFormOptions } from '@ngx-formly/core'; @Component({ selector: 'app-copy-schedule-from-site', template: `<formly-form [form]="form" [fields]="fields" [model]="model" [options]="options"></formly-form>` }) export class CopyScheduleFromSiteComponent implements OnInit { @Input() form: FormGroup; @Input() model: any; @Input() options: FormlyFormOptions; @Input() approvedSites: any[]; @Input() disableControls: boolean; fields: FormlyFieldConfig[] = []; ngOnInit(): void { this.fields = [ { fieldGroupClassName: 'row', fieldGroup: [ { wrappers: ['form-field'], className: 'col-6', key: 'siteScheduleControl', type: 'select', templateOptions: { label: 'Copy Schedule from Site', options: this.approvedSites, labelProp: 'text', }, expressionProperties: { 'templateOptions.disabled': () => this.disableControls } } ] } ] } }
- 在SiteScheduleComponent的模板中,插入子组件标签,传入父组件的表单相关实例,这一步完成后导入的组件就被实际使用,TS报错直接消失:
<!-- 在父组件原有formly表单的合适位置插入 --> <app-copy-schedule-from-site [form]="form" [model]="model" [options]="options" [approvedSites]="approvedSites" [disableControls]="siteSubmissionModel.disableControls" ></app-copy-schedule-from-site> <!-- 原有父组件的formly-form标签保留不变 -->
- 删除父组件fields数组中和
siteScheduleControl相关的重复定义,避免key冲突。改造完成后子组件的下拉字段会直接注册到父表单,选值自动同步到父组件的model,原有复制逻辑不需要调整。
注意事项
- 不要在父子组件中重复定义同一个key的Formly字段,会导致表单状态错乱。
- 跨组件共享Formly表单时必须共用同一个FormGroup实例,各自新建实例会导致数据完全不互通。
- 通用弹窗逻辑(比如你代码里的覆盖确认弹窗)建议抽到公共服务里,不要在多个组件重复实现。
内容的提问来源于stack exchange,提问作者developer8492
相关产品推荐
相关产品推荐

