Angular @angular/forms 公共 API 全解析:从 goldens/public-api/forms/index.api.md 读懂表单包完整接口面
本文以 Angular 仓库中 @angular/forms 的公共 API 快照文件 goldens/public-api/forms/index.api.md 为主体,系统讲解该 API 报告文件的生成与维护机制,并逐层剖析它记录的整套表单公共接口:模型层(AbstractControl/FormControl/FormGroup/FormArray)、FormBuilder 家族、验证器 API、模板驱动与响应式两套指令体系、ControlValueAccessor 值访问器与注入令牌、以及表单事件系统,帮助你在阅读源码、二次封装或升级依赖时精确掌握 @angular/forms 的公共契约。
API 报告文件是什么:生成器、快照与守护测试
index.api.md 文件头部明确标注了两条元信息:
API Report File for "@angular/forms" —— Do not edit this file. It is a report generated by API Extractor.
即它是由 API Extractor 工具从 @angular/forms 的 .d.ts 类型定义中提取、自动生成的公共 API 报告(API golden)。报告中每一条导出都带有 API-Extracter 的文档化层级标记(如 // @public、// @public (undocumented)),完整列出了 AbstractControl、FormControl、FormGroup、FormArray、FormBuilder、各表单指令、Validators 等全部公共成员的精确签名。它的价值在于:
- 契约快照:它是
@angular/forms对外发布接口的"权威清单",任何新增、删除或重命名公共成员都会导致该文件内容变化; - 变更门禁:仓库将其作为 Bazel 黄金文件测试(golden test)的一部分,在 CI 中比对实际 API 与快照是否一致,从而防止公共 API 被意外破坏。
快照如何生成与更新
维护流程在 goldens/README.md 中有明确说明:goldens/public-api/ 目录保存所有发布到 NPM 的包的公共 API 快照,并在所有 PR 和提交中作为 Bazel 测试运行。两条核心命令(定义于根 package.json):
pnpm public-api:check # 等价于 node goldens/public-api/manage.js test
pnpm public-api:update # 等价于 node goldens/public-api/manage.js accept
编排脚本 goldens/public-api/manage.js 的工作方式是:先通过 Bazel 查询出所有带 api_guard 标签的 js_test 目标,再对 test 模式逐个运行测试、对 accept 模式逐个运行对应的 <target>.accept 目标重新生成快照。
落到 @angular/forms 包,packages/forms/BUILD.bazel 中定义了两个守护目标:
api_golden_test_npm_package(
name = "forms_api",
data = [":npm_package", "//goldens:public-api"],
golden_dir = "goldens/public-api/forms",
npm_package = "packages/forms/npm_package",
)
api_golden_test(
name = "forms_errors",
entry_point = "src/errors.d.ts",
golden = "goldens/public-api/forms/errors.api.md",
)
前者对 npm 打包产物生成整个 goldens/public-api/forms/ 目录下的快照(即本文件所在目录),后者单独守护错误模块 src/errors.d.ts 的 API。而从源码结构看,公共入口由 packages/forms/public_api.ts 统一收敛——它只重导出 ./src/forms,注释要求"只 reexport src 文件夹内容",这正是 API Extractor 提取的边界。
模型层:AbstractControl 及其四个基本构建块
报告中最长的段落属于模型层(约 25–321 行),它定义了所有表单控件的公共行为契约。packages/forms/PACKAGE.md 将该包定位为实现"指令与 provider 集合,用于在构建表单时与原生 DOM 元素通信以捕获用户输入",而模型层就是这套契约的数据核心。
AbstractControl:状态、事件与标记位
AbstractControl 是抽象基类(报告中声明为 @public),其完整签名体现了三层设计:值、状态、事件。
export abstract class AbstractControl<
TValue = any,
TRawValue extends TValue = TValue,
TValueWithOptionalControlStates = any
> {
constructor(validators: ValidatorFn | ValidatorFn[] | null,
asyncValidators: AsyncValidatorFn | AsyncValidatorFn[] | null);
// 状态标志
get valid(): boolean; get invalid(): boolean;
get pending(): boolean; get disabled(): boolean; get enabled(): boolean;
get dirty(): boolean; get pristine(): boolean;
get touched(): boolean; get untouched(): boolean;
get status(): FormControlStatus;
// 错误访问
readonly errors: ValidationErrors | null;
getError(errorCode: string, path?: Array<string | number> | string): any;
hasError(errorCode: string, path?: Array<string | number> | string): boolean;
setErrors(errors: ValidationErrors | null, opts?: { emitEvent?: boolean }): void;
// 值操作
readonly value: TValue;
readonly valueChanges: Observable<TValue>;
readonly statusChanges: Observable<FormControlStatus>;
getRawValue(): any;
abstract patchValue(value: TValue, options?: Object): void;
abstract setValue(value: TRawValue, options?: Object): void;
abstract reset(value?: TValueWithOptionalControlStates, options?: Object): void;
// 树形关系
get parent(): FormGroup | FormArray | null;
get root(): AbstractControl;
setParent(parent: FormGroup | FormArray | null): void;
get<P extends string | readonly (string | number)[]>(path: P):
AbstractControl<ɵGetProperty<TRawValue, P>> | null;
// 状态标记与验证器管理(均支持 { onlySelf?, emitEvent? })
markAsTouched(opts?: { onlySelf?: boolean; emitEvent?: boolean }): void;
markAsDirty(opts?: { onlySelf?: boolean; emitEvent?: boolean }): void;
markAsPending(opts?: { onlySelf?: boolean; emitEvent?: boolean }): void;
...
addValidators(validators: ValidatorFn | ValidatorFn[]): void;
addAsyncValidators(validators: AsyncValidatorFn | AsyncValidatorFn[]): void;
hasValidator(validator: ValidatorFn): boolean;
hasAsyncValidator(validator: AsyncValidatorFn): boolean;
updateValueAndValidity(opts?: { onlySelf?: boolean; emitEvent?: boolean }): void;
// 更新时机与事件流
get updateOn(): FormHooks;
readonly events: Observable<ControlEvent<TValue>>;
}
几个值得注意的 API 设计点:
- 状态机:
FormControlStatus在报告中定义为联合类型'VALID' | 'INVALID' | 'PENDING' | 'DISABLED',与statusgetter、statusChangesObservable 配套; onlySelf语义:markAs*、updateValueAndValidity、setValue等普遍接受{ onlySelf?: boolean; emitEvent?: boolean },用于控制操作是否向父/子控件级联、是否发射事件——这是响应式表单中精细控制状态传播的关键开关;updateOn: FormHooks:报告将FormHooks具体化为'change' | 'blur' | 'submit'(见AbstractControlOptions),实现于 packages/forms/src/model/abstract_model.ts;events通道:Observable<ControlEvent<TValue>>是一个统一事件流,后续"事件系统"小节的ValueChangeEvent、StatusChangeEvent等都会流经它;- 泛型
get(path):用模板字面量式的路径类型推断子控件的值类型,AbstractControl<ɵGetProperty<TRawValue, P>>表明点路径取值时类型会被精确推导。
FormControl:单个输入框的模型
FormControl<TValue> 是接口式定义(继承 AbstractControl<TValue>),在报告中暴露了比基类更具体的能力:
export interface FormControl<TValue = any> extends AbstractControl<TValue> {
defaultValue: TValue;
getRawValue(): TValue;
registerOnChange(fn: Function): void;
registerOnDisabledChange(fn: (isDisabled: boolean) => void): void;
patchValue(value: TValue, options?: {
onlySelf?: boolean; emitEvent?: boolean;
emitModelToViewChange?: boolean; emitViewToModelChange?: boolean;
}): void;
setValue(value: TValue, options?: {
onlySelf?: boolean; emitEvent?: boolean;
emitModelToViewChange?: boolean; emitViewToModelChange?: boolean;
}): void;
reset(formState?: TValue | FormControlState<TValue>, options?: {
onlySelf?: boolean; emitEvent?: boolean; overwriteDefaultValue?: boolean;
}): void;
}
// @public (undocumented)
export const FormControl: ɵFormControlCtor;
配套的类型定义(实现见 packages/forms/src/model/form_control.ts):
/** 装箱值:value + disabled 两键必填 */
export interface FormControlState<T> { value: T; disabled: boolean; }
export interface FormControlOptions extends AbstractControlOptions {
nonNullable?: boolean; // 初始值即默认值,reset 后不回退为 null
/** @deprecated Use `nonNullable` instead. */
initialValueIsDefault?: boolean;
}
export interface AbstractControlOptions {
validators?: ValidatorFn | ValidatorFn[] | null;
asyncValidators?: AsyncValidatorFn | AsyncValidatorFn[] | null;
updateOn?: 'change' | 'blur' | 'submit';
}
从报告与源码可以确认几个语义:nonNullable: true 让初始值同时成为默认值,reset() 不带参数时回落到该值而非 null;旧的 initialValueIsDefault 选项已标记 @deprecated,报告将其同时保留以维持向后兼容。ɵFormControlCtor 这个"值导出"(报告中标注 @public (undocumented))是编译器内部实现构造函数,对外部使用者来说 new FormControl(...) 的调用形态不变。FormControlState<T> 支持用 { value, disabled } 形式同时携带初始值与禁用状态初始化控件。
FormGroup 与 FormRecord:具名控件集合
export class FormGroup<TControl extends { [K in keyof TControl]: AbstractControl<any> } = any>
extends AbstractControl<...> {
constructor(controls: TControl,
validatorOrOpts?: ValidatorFn | ValidatorFn[] | AbstractControlOptions | null,
asyncValidator?: AsyncValidatorFn | AsyncValidatorFn[] | null);
addControl(name: string, control: AbstractControl, options?: { emitEvent?: boolean }): void;
contains(controlName: string): boolean;
controls: TControl; // 具名子控件映射
getRawValue(): ...;
patchValue(value: ..., options?: { onlySelf?: boolean; emitEvent?: boolean }): void;
registerControl(name: string, control): ...;
removeControl(name: string, options?: { emitEvent?: boolean }): void;
reset(value?: ..., options?: { onlySelf?; emitEvent?; overwriteDefaultValue? }): void;
setControl(name: string, control: AbstractControl, options?: { emitEvent?: boolean }): void;
setValue(value: ..., options?: { onlySelf?: boolean; emitEvent?: boolean }): void;
}
FormGroup 的方法重载对泛型具名 key(K extends string & keyof TControl)与字符串 key 分别给出精确类型,removeControl 对可选 key 有专门的重载(ɵOptionalKeys<TControl> & S),从源码结构看这是为了在"运行时删除可选字段"时保持类型安全。
FormRecord 则是字符串键的 FormGroup 特化,报告中定义为 class FormRecord<TControl> extends FormGroup<{ [key: string]: TControl }> {},并提供同名接口形式描述其成员方法,适用于控件数量动态、键名不固定的场景。
FormArray:顺序控件集合
export class FormArray<TControl extends AbstractControl<any> = any>
extends AbstractControl<...> {
constructor(controls: Array<TControl>,
validatorOrOpts?: ValidatorFn | ValidatorFn[] | AbstractControlOptions | null,
asyncValidator?: AsyncValidatorFn | AsyncValidatorFn[] | null);
at(index: number): TControl;
clear(options?: { emitEvent?: boolean }): void;
controls: Array<TControl>;
getRawValue(): ...;
insert(index: number, control: TControl, options?: { emitEvent?: boolean }): void;
get length(): number;
patchValue(value: ..., options?: { onlySelf?; emitEvent? }): void;
push(control: TControl | Array<TControl>, options?: { emitEvent?: boolean }): void;
removeAt(index: number, options?: { emitEvent?: boolean }): void;
reset(value?: ..., options?: { onlySelf?; emitEvent?; overwriteDefaultValue? }): void;
setControl(index: number, control: TControl, options?: { emitEvent?: boolean }): void;
setValue(value: ..., options?: { onlySelf?; emitEvent? }): void;
}
FormArray 提供 push/insert/removeAt/setControl/at/clear 的完整列表操作,且几乎所有变更方法都接受 emitEvent 选项,与 FormGroup 的 setControl/addControl/removeControl 对应,共同构成动态表单的数据基础。
FormBuilder 家族:group / control / array / record 与类型变体
报告中的 FormBuilder 是 @Injectable(可见 static ɵprov 注入声明),提供四个工厂方法与一个非空变体:
export class FormBuilder {
control(formState: T | FormControlState<T>,
validatorOrOpts?: ValidatorFn | ValidatorFn[] | FormControlOptions | null,
asyncValidator?: AsyncValidatorFn | AsyncValidatorFn[] | null): FormControl<T | null>;
// 非空重载
control<T>(formState: T | FormControlState<T>,
opts: FormControlOptions & { nonNullable: true }): FormControl<T>;
group<T extends {}>(controls: T, options?: AbstractControlOptions | null): FormGroup<...>;
array<T>(controls: Array<T>, validatorOrOpts?: ..., asyncValidator?: ...): FormArray<...>;
record<T>(controls: { [key: string]: T }, options?: AbstractControlOptions | null): FormRecord<...>;
get nonNullable(): NonNullableFormBuilder;
}
要点:
- 默认值类型包含
null:FormBuilder.control的通用重载返回FormControl<T | null>,这与FormControl文档注释一致——"控件被 reset 后会变成null"; nonNullable双通道:既可以在control()单控件上通过{ nonNullable: true }重载得到FormControl<T>,也可以通过this.fb.nonNullable.group(...)得到NonNullableFormBuilder,其group/array/control/record全部返回非空值类型(ɵNonNullableFormControls<T>、ɵElement<T, never>等);group的第二个参数弃用重载:报告保留了group(controls: {[key: string]: any}, options: {[key: string]: any})并标注@deprecated,历史上曾用于"逐控件选项",现已由AbstractControlOptions取代;- Untyped 变体:
UntypedFormBuilder(继承FormBuilder,group/array/control返回UntypedFormGroup/UntypedFormArray/UntypedFormControl)、UntypedFormGroup = FormGroup<any>、UntypedFormControl = FormControl<any>、UntypedFormArray = FormArray<any>,均带ɵ*实现构造函数导出,服务于未迁移到类型化 API 的旧代码; - 辅助配置类型
ControlConfig<T> = [T | FormControlState<T>, (ValidatorFn | ValidatorFn[])?, (AsyncValidatorFn | AsyncValidatorFn[])?]是位置元组形式的控件配置。
FormBuilder 的实现位于 packages/forms/src/form_builder.ts。
验证 API:静态 Validators 与内置验证器指令
报告中的 Validators 类提供纯函数式验证器(实现见 packages/forms/src/validators.ts):
export class Validators {
static compose(validators: (ValidatorFn | null | undefined)[]): ValidatorFn | null;
static composeAsync(validators: (AsyncValidatorFn | null)[]): AsyncValidatorFn | null;
static email(control: AbstractControl): ValidationErrors | null;
static max(max: number): ValidatorFn;
static maxLength(maxLength: number): ValidatorFn;
static min(min: number): ValidatorFn;
static minLength(minLength: number): ValidatorFn;
static nullValidator(control: AbstractControl): ValidationErrors | null;
static pattern(pattern: string | RegExp): ValidatorFn;
static required(control: AbstractControl): ValidationErrors | null;
static requiredTrue(control: AbstractControl): ValidationErrors | null;
}
export type ValidationErrors = { [key: string]: any };
export interface ValidatorFn { (control: AbstractControl): ValidationErrors | null; }
export interface AsyncValidatorFn {
(control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null>;
}
export interface Validator {
registerOnValidatorChange?(fn: () => void): void;
validate(control: AbstractControl): ValidationErrors | null;
}
export interface AsyncValidator extends Validator {
validate(control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null>;
}
Validator(类方法式)与 ValidatorFn(函数式)双形态并存,AbstractControl 的 addValidators/setValidators/hasValidator 等方法同时接受两者,这是自定义验证器可以以"可注入类"形式复用的原因。
另一组是绑定到模板属性的内置验证器指令,它们的 selector 都同时匹配 [formControlName]、[formControl]、[ngModel] 三种场景(见报告 635–931 行):
| 指令 | 报告中的 selector 核心 | 绑定属性 |
|---|---|---|
RequiredValidator |
:not([type=checkbox])[required] |
required |
CheckboxRequiredValidator |
input[type=checkbox][required] |
—(复用 required 语义) |
EmailValidator |
[email] |
email |
MinLengthValidator / MaxLengthValidator |
[minlength] / [maxlength] |
minlength / maxlength |
MinValidator / MaxValidator |
input[type=number][min] / [max] |
min / max |
PatternValidator |
[pattern] |
pattern: string | RegExp |
这些指令均继承 AbstractValidatorDirective,通过 NG_VALIDATORS 多令牌注入到控件的验证管线中(见下文令牌小节)。
指令体系:模板驱动 vs 响应式两套 selector
报告记录了表单与 DOM 通信的全部指令契约。两类体系的 selector 设计(来自各指令的 ɵdir 声明)值得精确记忆:
响应式表单指令(ReactiveFormsModule 提供)
FormGroupDirective:selector[formGroup],导出form: FormGroup输入与ngSubmit输出;FormControlDirective:selector[formControl],输入别名formControl、disabled(isDisabled)、ngModel(已弃用的model);FormControlName:selector[formControlName],需要name与父级ControlContainer;FormArrayDirective:selector[formArray];FormArrayName/FormGroupName:selector[formArrayName]/[formGroupName],用于嵌套分组。
FormGroupDirective 等继承自 AbstractFormDirective,其公共契约(报告 144–181 行)包含:
abstract class AbstractFormDirective extends ControlContainer
implements Form, OnChanges, OnDestroy {
directives: FormControlName[];
addControl(dir: FormControlName): FormControl;
addFormGroup(dir: FormGroupName): void;
addFormArray(dir: FormArrayName): void;
getControl(dir: FormControlName): FormControl;
getFormGroup(dir: FormGroupName): FormGroup;
getFormArray(dir: FormArrayName): FormArray;
removeControl(dir: FormControlName): void;
...
resetForm(value?: any, options?: { onlySelf?: boolean; emitEvent?: boolean }): void;
get submitted(): boolean;
updateModel(dir: FormControlName, value: any): void;
onSubmit($event: Event): boolean;
}
Form 接口(报告 275–283 行)则抽出了"容器如何登记/更新控件"的最小契约:addControl / addFormGroup / getControl / getFormGroup / removeControl / removeFormGroup / updateModel。
模板驱动指令(FormsModule 提供)
NgForm:selectorform:not([ngNoForm]):not([formGroup]):not([formArray]), ng-form, [ngForm]——即任意未禁用表单行为的原生<form>都会被接管;输入ngFormOptions({ updateOn?: FormHooks }),输出ngSubmit;NgModel:selector[ngModel]:not([formControlName]):not([formControl]),输入name、ngModel(别名model)、ngModelOptions({ name?, standalone?, updateOn? })、disabled,输出ngModelChange(update已弃用);NgModelGroup:selector[ngModelGroup];NgSelectOption:selectoroption,支持value与ngValue。
从 selector 可以读出两条硬性约束:其一,[ngModel] 与 [formControl]/[formControlName] 在 selector 层面互斥,报告同时保留了 ReactiveFormsModule.withConfig 中的 warnOnNgModelWithFormControl: 'never' | 'once' | 'always' 配置项用于在运行时兜底警告混用;其二,ngNoForm / ngNoCva 属性提供了对原生 <form> 与内置值访问器的逃生舱。
ControlValueAccessor 体系与注入令牌
报告定义的 ControlValueAccessor 接口是连接控件模型与 DOM 元素的核心契约(实现位于 packages/forms/src/directives/control_value_accessor.ts):
export interface ControlValueAccessor {
writeValue(obj: any): void;
registerOnChange(fn: any): void;
registerOnTouched(fn: any): void;
setDisabledState?(isDisabled: boolean): void;
}
内置值访问器(BuiltInControlValueAccessor 子类)按 selector 精确匹配不同元素:
| 值访问器 | selector(报告 ɵdir 核心) |
|---|---|
DefaultValueAccessor |
input:not([type=checkbox])、textarea(均排除 [ngNoCva]) |
CheckboxControlValueAccessor |
input[type=checkbox] |
RadioControlValueAccessor |
input[type=radio],配合 RadioControlRegistry 管理同组单选 |
SelectControlValueAccessor |
select:not([multiple]),支持 compareWith |
SelectMultipleControlValueAccessor |
select[multiple] |
NumberValueAccessor |
input[type=number](写回 number | null) |
RangeValueAccessor |
input[type=range] |
所有内置 selector 都带有 :not([ngNoCva]) 守卫,且同时匹配三种表单指令属性,保证在模板驱动、响应式及独立 ngModel 场景下都能正确接入。
相关注入令牌(报告 671–677 行):
export const NG_VALIDATORS: InjectionToken<readonly (Function | Validator)[]>;
export const NG_ASYNC_VALIDATORS: InjectionToken<readonly (Function | Validator)[]>;
export const NG_VALUE_ACCESSOR: InjectionToken<readonly ControlValueAccessor[]>;
export const COMPOSITION_BUFFER_MODE: InjectionToken<boolean>;
NG_VALIDATORS/NG_ASYNC_VALIDATORS:多令牌收集同作用域内的验证器,供NgControl在创建控件时装配;NG_VALUE_ACCESSOR:多令牌提供值访问器,NgControl依此选择(自定义控件可覆盖默认 DOM 绑定);COMPOSITION_BUFFER_MODE:控制 IME 组合输入(如中文输入法)期间是否缓冲变更,DefaultValueAccessor构造器中的_compositionMode: boolean即消费该令牌。
NgControl 是全部控件指令的公共父类,报告暴露了它的扩展点:customControlBindings(支持 value/disabled/touched/dirty/valid/invalid/pending/required/errors 的自定义绑定)、valueAccessor、抽象方法 viewToModelUpdate 等;NgControlStatus / NgControlStatusGroup 则分别针对 [formControlName]/[ngModel]/[formControl] 与分组 selector,把状态类自动绑定到元素上,免去手写 [ngClass]。
事件系统与模块配置
报告定义了一套统一的表单事件层次,全部继承自抽象基类 ControlEvent<T>(abstract readonly source: AbstractControl<unknown>):
export class ValueChangeEvent<T> extends ControlEvent<T> {
constructor(value: T, source: AbstractControl);
readonly value: T;
}
export class StatusChangeEvent extends ControlEvent {
constructor(status: FormControlStatus, source: AbstractControl);
readonly status: FormControlStatus;
}
export class TouchedChangeEvent extends ControlEvent {
constructor(touched: boolean, source: AbstractControl);
readonly touched: boolean;
}
export class PristineChangeEvent extends ControlEvent {
constructor(pristine: boolean, source: AbstractControl);
readonly pristine: boolean;
}
export class FormResetEvent extends ControlEvent { constructor(source: AbstractControl); }
export class FormSubmittedEvent extends ControlEvent { constructor(source: AbstractControl); }
这些事件对象(而非裸值)通过 AbstractControl.events: Observable<ControlEvent<TValue>> 通道分发,订阅方可以按事件类型区分"值变化"、"状态变化"、"touched/pristine 变化"、"重置"与"提交",并始终能拿到 source 控件引用。
两个 NgModule 的配置面:
export class FormsModule {
static withConfig(opts: { callSetDisabledState?: SetDisabledStateOption }): ModuleWithProviders<FormsModule>;
}
export class ReactiveFormsModule {
static withConfig(opts: {
warnOnNgModelWithFormControl?: 'never' | 'once' | 'always';
callSetDisabledState?: SetDisabledStateOption;
}): ModuleWithProviders<ReactiveFormsModule>;
}
export type SetDisabledStateOption = 'whenDisabledForLegacyCode' | 'always';
callSetDisabledState: 'always' 要求所有自定义 ControlValueAccessor 必须实现 setDisabledState,从而获得更严格的禁用状态管理;warnOnNgModelWithFormControl 对应前文 selector 无法覆盖的运行时混用场景。报告还保留了四个类型守卫 isFormControl / isFormGroup / isFormArray / isFormRecord,便于在 any 化的控件集合(如遍历 controls)上做运行时判别,以及 VERSION(Version 类型)用于版本查询。
如何阅读这份 golden:实用技巧
- 以
// @public分层为准:报告中每个成员前的// @public/// @public (undocumented)标记是 API 文档化的真实层级;static ɵdir、static ɵfac、static ɵprov、ɵFormControlCtor等带ɵ前缀的成员是 Angular 编译产物(指令声明、工厂、注入声明)的序列化形式,属于"公共但内部"的实现面,业务代码不应依赖; - 与源码对照阅读:模型层对应 packages/forms/src/model/ 下的 abstract_model.ts、form_control.ts、form_group.ts、form_array.ts;指令层对应 packages/forms/src/directives/,其中 ng_model.ts、ng_form.ts、default_value_accessor.ts 与报告中的
NgModel、NgForm、DefaultValueAccessor一一对应;验证器对应 packages/forms/src/validators.ts; - 验证快照一致性:改动
packages/forms公共 API 后,本地运行pnpm public-api:check查看差异,确认符合预期后运行pnpm public-api:update重新生成 golden(流程见 goldens/README.md 与 goldens/public-api/manage.js); - 注意 API 面的边界:本文件只覆盖
@angular/forms主入口;同目录还有errors.api.md守护错误模块,而信号表单(form()/schema()/[formField],见 packages/forms/PACKAGE.md 的三种构建方式)位于packages/forms/signals子入口,拥有独立的 golden 文件,不在这份报告中出现。
小结
goldens/public-api/forms/index.api.md 以 API Extractor 快照的形式,固化了 @angular/forms 的完整公共契约:模型层以 AbstractControl 的"值 / 状态 / 事件"三支柱为核心,向下派生 FormControl、FormGroup、FormArray、FormRecord;FormBuilder 家族提供类型化、非空化、未类型化三档构造体验;验证 API 提供函数式与指令式双通道;指令体系通过互斥的 selector 设计划清模板驱动与响应式两套用法;ControlValueAccessor 与 NG_VALUE_ACCESSOR/NG_VALIDATORS 令牌则是自定义控件与验证器的扩展锚点。理解这份报告,就掌握了在 Angular 中构建、校验、扩展表单时全部可用的公共接口边界。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python07
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00