☰
ng-zorro-antd Cron Expression 结合 Angular 响应式表单:formControlName、自定义校验器与执行时间预览
2026/9/25 4:07:47 网站建设 项目流程
  • UI组件
  • 前端

【免费下载链接】ng-zorro-antd

Angular UI Component Library based on Ant Design

项目地址:https://gitcode.com/gh_mirrors/ng/ng-zorro-antd
点击查看免费下载

ng-zorro-antd 的nz-cron-expression组件提供可视化的 cron 表达式编辑能力。本篇基于官方示例 form(v22.1.0 引入),讲解如何将该组件通过formControlName接入 Angular 响应式表单,如何用cron-parser编写业务级自定义校验器(例如“最小执行间隔 1 天”),并展示错误信息的语义化渲染与底层ControlValueAccessor校验机制,帮助你在定时任务配置类表单中直接落地该组件。

快速开始:用 formControlName 绑定

官方 form 示例 的核心就一行模板代码:

<nz-cron-expression formControlName="cron" />

前提是所在组件的模板处于ReactiveFormsModule(或formGroup指令)的管辖范围内,且FormGroup中已声明名为cron的FormControl。组件实现了ControlValueAccessor,会自动与表单控件完成双向同步:

  • 表单值(字符串,如* 1 * * *)写入组件时,组件将其拆分为各时间字段分别渲染到输入框;
  • 用户修改任意字段时,组件将各字段按固定顺序拼回空格分隔的字符串并通过onChange回写表单。

完整示例:多规则、多类型的 cron 表单

form.ts 演示了一个完整的定时任务表单,包含普通文本输入、Linux cron、Spring cron 以及带自定义校验器的最小间隔限制四个字段:

<form nz-form nzLayout="vertical" [formGroup]="form" (ngSubmit)="submit()"> <nz-form-item> <nz-form-label [nzSpan]="6">name</nz-form-label> <nz-form-control [nzSpan]="14"> <input nz-input formControlName="username" /> </nz-form-control> </nz-form-item> <nz-form-item> <nz-form-label [nzSpan]="6">nz-cron-linux</nz-form-label> <nz-form-control [nzSpan]="14"> <nz-cron-expression formControlName="cronLinux" /> </nz-form-control> </nz-form-item> <nz-form-item> <nz-form-label [nzSpan]="6">nz-cron-spring</nz-form-label> <nz-form-control [nzSpan]="14"> <nz-cron-expression formControlName="cronSpring" nzType="spring" /> </nz-form-control> </nz-form-item> <nz-form-item> <nz-form-label [nzSpan]="6">minimum interval: 1 day</nz-form-label> <nz-form-control [nzSpan]="14"> <nz-cron-expression formControlName="cronMinInterval" [nzSemantic]="form.controls.cronMinInterval.hasError('minInterval') ? minIntervalError : null" /> <ng-template #minIntervalError> <span class="ant-cron-expression-error">The interval cannot be less than 1 day.</span> </ng-template> </nz-form-control> </nz-form-item> <nz-form-item> <nz-form-control> <button nz-button nzType="primary" [disabled]="!form.valid">submit</button> </nz-form-control> </nz-form-item> </form>

对应的组件与表单定义(含自定义校验器):

import { Component, inject } from '@angular/core'; import { FormBuilder, FormControl, FormGroup, ReactiveFormsModule, ValidatorFn, Validators } from '@angular/forms'; import { CronExpressionParser } from 'cron-parser'; import { NzButtonModule } from 'ng-zorro-antd/button'; import { NzCronExpressionModule } from 'ng-zorro-antd/cron-expression'; import { NzFormModule } from 'ng-zorro-antd/form'; import { NzInputModule } from 'ng-zorro-antd/input'; const ONE_DAY_IN_MILLISECONDS = 24 * 60 * 60 * 1000; @Component({ selector: 'nz-demo-cron-expression-form', imports: [ReactiveFormsModule, NzButtonModule, NzCronExpressionModule, NzFormModule, NzInputModule], template: `...` // 见上方模板 }) export class NzDemoCronExpressionFormComponent { private readonly fb = inject(FormBuilder); private readonly minIntervalValidator: ValidatorFn = control => { if (typeof control.value !== 'string' || !control.value) { return null; } try { const interval = CronExpressionParser.parse(control.value); const firstExecution = interval.next().toDate(); const secondExecution = interval.next().toDate(); return secondExecution.getTime() - firstExecution.getTime() < ONE_DAY_IN_MILLISECONDS ? { minInterval: true } : null; } catch { return null; // 语法错误交由组件内部校验器标记 } }; readonly form: FormGroup<{ username: FormControl<string | null>; cronLinux: FormControl<string | null>; cronMinInterval: FormControl<string | null>; cronSpring: FormControl<string | null>; }> = this.fb.group({ username: ['cron-expression', [Validators.required]], cronLinux: ['* 1 * * *', [Validators.required]], cronSpring: ['0 * 1 * * *', [Validators.required]], cronMinInterval: ['0 */12 * * *', [Validators.required, this.minIntervalValidator]] }); constructor() { this.form.controls.cronMinInterval.markAsTouched(); } submit(): void { console.log(this.form.value); } }

实现要点:

  • nzType决定字段数:默认linux类型为 5 段(分、时、日、月、周);nzType="spring"时扩展为 6 段(增加秒位)。从 form.ts 可见两个默认值分别为* 1 * * *与0 * 1 * * *,段数正好不同。
  • 提交按钮受表单有效性控制:[disabled]="!form.valid",组件内部校验失败(如某段填入非法值)会使FormGroup无效,从而自动禁用提交。
  • 构造器中markAsTouched():初始化即触发校验显示,用户无需先聚焦字段就能看到*/12与“最小间隔 1 天”约束的冲突。
  • 自定义校验器与组件内部校验分工:minIntervalValidator只负责业务规则(两次执行间隔 ≥ 24 小时);表达式本身的语法合法性由组件自带的校验器兜底(详见下文源码解析),因此try/catch中解析失败时返回null,把“格式错误”交由组件标记。

用 nzSemantic 渲染错误信息

示例中第三个字段的[nzSemantic]绑定了一个三元表达式:当cronMinInterval控件携带minInterval错误时,传入#minIntervalError模板;否则传null。

从 cron-expression-preview.component.ts 的模板可以看到nzSemantic的渲染位置:预览区默认显示下一次执行时间(TimeList[0] | date: 'yyyy-MM-dd HH:mm:ss'),一旦提供nzSemantic模板则改为渲染该模板内容。配合样式类ant-cron-expression-error,即可把预览区复用为错误提示区,无需额外的错误文案 DOM。

API 参数说明

以下为 组件文档 中nz-cron-expression的完整参数表:

参数说明类型默认值版本
[nzType]cron 规则类型'linux'|'spring'linux
[nzSize]设置输入框大小'large'|'small'|'default'default
[nzDisabled]禁用booleanfalse
[nzBorderless]是否隐藏边框booleanfalse
[nzStatus]设置校验状态'error'|'warning'-22.1.0
[nzCollapseDisable]隐藏折叠面板booleanfalse
[nzExtra]自定义渲染右侧的内容TemplateRef<void>-
[nzSemantic]自定义渲染下次执行时间TemplateRef<void>-

注意:该组件在文档中标记为experimental: true(见 index.zh-CN.md 的 frontmatter),使用前建议关注版本更新。

支持的 cron 格式

文档给出的字段布局(Spring 类型 6 段):

* * * * * * ┬ ┬ ┬ ┬ ┬ ┬ │ │ │ │ │ | │ │ │ │ │ └ day of week (0 - 7, 1L - 7L) (0 or 7 is Sun) │ │ │ │ └───── month (1 - 12) │ │ │ └────────── day of month (1 - 31, L) │ │ └─────────────── hour (0 - 23) │ └──────────────────── minute (0 - 59) └───────────────────────── second (0 - 59, optional)

Linux 类型省略秒位,即 5 段。

源码解析:表单集成的实现机制

阅读 cron-expression.component.ts 可以确认组件如何同时扮演表单控件与校验器两个角色:

1. CVA 与校验器的双注册

组件声明了两个多提供者(cron-expression.component.ts#L110-L121):

providers: [ { provide: NG_VALIDATORS, useExisting: forwardRef(() => NzCronExpressionComponent), multi: true }, { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => NzCronExpressionComponent), multi: true } ]

这正是formControlName="cron"可以直接生效的原因:NG_VALUE_ACCESSOR让它与FormControl双向绑定,NG_VALIDATORS让它参与表单校验树,校验失败会向上影响form.valid,从而联动示例中的提交按钮禁用逻辑。

2. 值的拆分与回写

  • writeValue(value)→convertFormat(value)(L190-L203):把表单传入的字符串按空格split,按当前labels顺序映射到内部second/minute/hour/day/month/week六个非空FormControl上,再patchValue渲染;
  • 内部表单valueChanges订阅中(L231-L235):每次字段变化都会Object.values(value).join(' ')拼回字符串调用onChange回写外层表单,并刷新预览时间列表。

这里labels由nzType决定(labelsOfType,L49-L54):spring返回 6 段(含second),linux返回 5 段。ngOnChanges中检测nzType变化后会重新计算 labels 并启用/禁用秒位字段(L238-L253),所以动态切换nzType也是安全的。

3. 内置语法校验与对外 validate()

组件内部的cronValidatorFn(L153-L163)把六个字段拼回完整表达式后用CronExpressionParser.parse试解析,抛出异常即返回{ error: true };对外的validate()(L213-L215)则将内部表单的有效性透传给外层表单。这意味着:即便你在FormControl上只挂了Validators.required,非法的 cron 片段同样会使form.valid变为false。

4. 校验状态的计算与继承

组件用三个信号合成最终状态(L176-L185):

private readonly finalStatus = computed(() => this.internalFormStatus() === 'INVALID' ? 'error' : this.inheritedStatus() );
  • internalFormStatus来自内部表单的statusChanges;
  • inheritedStatus优先取父级nz-form-control通过NzFormStatusService下发的状态,否则退回nzStatus输入;
  • 内部校验失败(INVALID)始终优先呈现为error,覆盖外部warning等状态。

测试用例 cron-expression.spec.ts 印证了这套行为:

  • form块中验证了FormControl.disable()会通过setDisabledState传导到组件,为输入组添加ant-input-disabled类,以及父级FormControl的setErrors({ external: true })会反映为ant-input-status-error类;
  • form status块中it.each(['error', 'warning', 'success', 'validating'])验证了nz-form-control的nzValidateStatus能透传到组件;
  • should prioritize internal validation error用例则验证了上文第 4 点的优先级:外部warning状态下人为写入非法的minute值后,最终类名变为ant-input-status-error而非warning。

5. 预览区与“加载更多”

每次值变化后previewDate(L255-L268)调用CronExpressionParser.parse计算未来 5 次执行时间;表达式非法时捕获异常、预览区不显示时间。折叠预览展开后可触发loadMorePreview(L270-L280)继续追加 5 条。预览组件在form.valid为false时(visible输入为 false)显示locale.cronError文案,该文案来自 i18n 服务(组件ngOnInit中通过NzI18nService.getLocaleData('CronExpression')获取,并订阅localeChange实时刷新)。

依赖与引入方式

  • 组件文档要求先安装解析库:npm install cron-parser@^5.5.0;组件库的 package.json 中同样声明了"cron-parser": "^5.5.0"依赖。若你要在业务代码中自写校验器(如上文的minIntervalValidator),建议直接使用该库的CronExpressionParser保持行为一致。
  • Angular 包内提供独立的 NzCronExpressionModule,ng-zorro-antd/cron-expression入口导出该模块、组件与 typings(含Cron、NzCronExpressionType、NzCronExpressionSize等类型)。

小结

将nz-cron-expression接入表单的关键路径是:formControlName完成值绑定(CVA),组件内置的NG_VALIDATORS保证表达式语法合法性,业务方再通过ValidatorFn+cron-parser叠加如最小执行间隔之类的领域规则,并用nzSemantic模板把错误提示就地渲染在预览区。上述机制均可在 cron-expression.component.ts 与 cron-expression.spec.ts 中找到对应实现与测试依据。

  • UI组件
  • 前端

【免费下载链接】ng-zorro-antd

Angular UI Component Library based on Ant Design

项目地址:https://gitcode.com/gh_mirrors/ng/ng-zorro-antd
点击查看免费下载
上一篇:Hydra version_base 参数详解:兼容默认值的三类取值与源码级演进
下一篇:Venera下载管理器:高效管理与全场景离线阅读指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询