You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Angular信号表单实现动态Schema?

Angular动态表单Schema生成问题

我为简化表单管理编写了如下Angular表单组件:

export type MyFormModel = Record<string, number|string>;

export type MyFormFields = MyFormField[];
export type MyFormField = MyFormFieldRange | MyFormFieldText;
export interface MyFormFieldRange {
  type: "range";
  key: string;
  min: number;
  max: number;
}
export interface MyFormFieldText {
  type: "text";
  key: string;
  required?: boolean;
}

export class MyForm {
  fields = input.required<MyFormFields>();
  model = model<MyFormModel>({});

  form = form(this.model);
}

我需要根据传入的fields动态生成表单Schema,但尝试多种方式均报错:

  • 用computed信号初始化form时,触发错误:

_effect-chunk2.mjs:2601 ERROR RuntimeError: NG0203: The _Injector token injection failed. inject() function must be called from an injection context such as a constructor, a factory function, a field initializer, or a function used with runInInjectionContext.

  • 在ngOnInit或ngOnChanges中延迟初始化form,同样出现上述错误。

  • 在Schema函数中直接使用fields,出现错误:

ERROR RuntimeError: NG0950: Input "fields" is required but no value is available yet.


解决方法

1. 用runInInjectionContext包裹表单生成逻辑

computed和生命周期钩子不在默认注入上下文内,需要手动注入Injector并调用runInInjectionContext来创建表单:

import { inject, runInInjectionContext, input, model, form } from '@angular/core';

export class MyForm {
  private injector = inject(Injector);
  fields = input.required<MyFormFields>();
  model = model<MyFormModel>({});

  form = computed(() => {
    return runInInjectionContext(this.injector, () => {
      // 根据fields生成表单控件配置
      const controlConfig: Record<string, any> = {};
      this.fields().forEach(field => {
        switch(field.type) {
          case 'range':
            controlConfig[field.key] = form.control(0, { min: field.min, max: field.max });
            break;
          case 'text':
            controlConfig[field.key] = form.control('', field.required ? { required: true } : {});
            break;
        }
      });
      return form.group(controlConfig);
    });
  });
}

2. 依赖computed的信号追踪确保fields就绪

computed会自动监听fields信号的变化,只有当fields()有有效值时才会执行内部逻辑,从根本上避免NG0950错误。

3. 禁止在生命周期钩子中直接创建表单

Angular响应式表单API(如form.group、form.control)必须在注入上下文内调用,所以不要在ngOnInit等钩子中直接初始化表单,改用computed配合runInInjectionContext实现动态生成。


内容的提问来源于stack exchange,提问作者LoganMzz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.01 19:59:52