Angular 表单库 | ng-hub-ui-forms

无障碍的 Angular 表单字段(input、textarea、滑块、select、日期选择器),在控件、组和表单级别自动显示校验错误,支持响应式表单和 CSS 变量。

API 参考

这里是 forms 的完整契约:你可以绑定、监听、投影和设置主题的一切,都集中在一处。接入你需要的部分,自定义你想要的样式——它是 standalone 的,且对 signal 友好。

输入

通过 87 个输入项精细调校 forms。像绑定任意 Angular @Input 一样绑定它们。

名称类型默认值描述
formControlName / [formControl]string | FormControl将任意字段绑定到响应式控件。当控件被触碰且无效时自动显示错误。
labelstring''字段标签文本。
labelType (hub-input, hub-select, hub-datepicker)'stacked' | 'floating' | 'horizontal''stacked'标签位置。`floating` 会把标签置于控件内部,在字段获得焦点或持有值之前,由它代替占位符。
labelType (hub-textarea, hub-otp-input, hub-slider, hub-segmented, hub-timepicker)'stacked' | 'horizontal''stacked'标签位置。这些字段没有 `floating` 变体:传入 `floating` 时,它们会渲染为堆叠式标签。
placeholder (hub-input, hub-select, hub-textarea, hub-datepicker)string'' / NgSelectConfig.placeholder (hub-select)占位符文本。
formTextstring显示在控件下方的辅助文本。
type (hub-input) — file is deprecated'text' | 'number' | 'password' | 'email' | 'tel' | 'url' | 'color' | 'checkbox' | 'switch' | 'counter' | 'file''text'hub-input 的格式。
passwordRevealed (hub-input)booleanfalse密码字段可见状态的双向绑定。点击眼睛按钮会更新它;设置该值可显示或隐藏密码。
passwordToggle (hub-input)booleantrue是否在密码字段上渲染内置的显示/隐藏切换按钮。
hideOnBlur (hub-input)booleantrue字段失去焦点时,已显示的密码是否自动重新隐藏。
capsLockWarning (hub-input)booleantrueCaps Lock 激活时,是否在字段下方显示提示。
passwordStrength (hub-input)booleanfalse在字段下方渲染可选的 4 段强度指示器。评分逻辑可通过 provideHubForms 覆盖。
autocomplete (hub-input)string''原生 autocomplete 属性,例如为密码管理器指定 current-password 或 new-password。
clearable (hub-input)booleanfalse为 true 时,字段有值后显示内置的 ✕ 按钮;点击可清空控件并发出空的搜索词。
debounceTime (hub-input)number0触发 search 事件前的防抖毫秒数(0 表示每次按键)。
mask (hub-input)string文本格式的模式掩码。标记:0 = 数字,A = 字母,* = 字母或数字;其他字符为字面分隔符。例如 "0000 0000 0000 0000"。
unmaskValue (hub-input)booleanfalse设置掩码后,在表单中存储原始输入的字符(无分隔符),而非格式化后的文本。
range (hub-slider)booleanfalse双滑块范围选择器;值变为 [lower, upper] 元组。
options (hub-segmented)HubSegmentedOption[][]hub-segmented 中可选中的选项,按渲染顺序排列——每一项为 { value, label, disabled? }。
size (hub-segmented)'sm' | 'md' | 'lg''md'分段控件的视觉密度:'sm'、'md'(默认)或 'lg'。
disabled (all fields)boolean (two-way, model)false禁用该字段。所有字段都从共享基类继承它,并且是双向的——通过响应式控件被禁用的字段会把这一变化回报出来。在 `hub-segmented` 上,各个选项还可以通过 `option.disabled` 单独退出。
multiple (hub-segmented)booleanfalse允许选择多个选项;值变为数组,选项以 aria-pressed 切换。
vertical (hub-segmented)booleanfalse将分段垂直堆叠,而非水平排列。
vertical (hub-select) — deprecatedbooleanfalse已弃用,且与同样已弃用的非 dropdown 格式绑定:将 buttons/checkbox/radio 选项垂直排列。请改用 `<hub-segmented [vertical]="true">`。
color (hub-segmented)'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'neutral' | string''所选分段的语义强调色(primary、success 等)或任意颜色;单选模式下滑动。
value (hub-segmented)unknown | unknown[]undefined可双向绑定的选中值(model()):单选模式下为所选选项的值,多选模式下为所选值的数组。会发出 valueChange;通常改由 formControlName 驱动。
format (hub-select) — deprecated for buttons/checkbox/radio'dropdown' | 'buttons' | 'checkbox' | 'radio''dropdown'select 渲染相同值的方式。
prepend / append (hub-input, hub-select, hub-textarea, hub-datepicker, hub-timepicker)string | string[]''任何以方框形式呈现的字段上的静态组附加内容:字符串为一个附加项,数组为一串附加项,空条目会被丢弃而不会绘制成空框。附加项与字段共用边框且不可获得焦点——若需要贴在边缘的可交互控件,请改用 [hubPrepend] / [hubAppend] 模板。两者可以同时存在,投影内容始终是其所在一侧最外层的元素。
items / bindLabel / bindValue / multiple (hub-select)any[] / string / string / boolean选项、对象项的 label/value 属性名,以及多选设置。
groupBy (hub-select)string | undefinedundefined用于将下拉选项归入选项组标题之下的属性名(点路径)。
searchable / clearable (hub-select)booleantrue选项是否可通过键入进行筛选(searchable),以及是否可用内置的清除按钮清空所选值(clearable)。两者默认均为 true。
closeOnSelect (hub-select)booleantrue选中条目后下拉框是否关闭。设为 false 可在 multiple 模式下挑选多个值时保持其打开。
fixedPlaceholder (hub-select)booleanfalse即使已选中值也保持占位符可见。默认为 false(选中后占位符隐藏),反转了 ng-select v23 不合常规的默认行为。
loading / notFoundText (hub-select)boolean / stringfalse / NgSelectConfig.notFoundTextloading 在异步获取条目期间渲染下拉框的加载状态;notFoundText 则是没有条目匹配搜索词时显示的消息。
readonly (hub-input, hub-select, hub-textarea, hub-datepicker, hub-otp-input, hub-timepicker)booleanfalse为 true 时,字段显示其值但拒绝任何交互,既不带 disabled 样式,也不改变表单状态。
appendTo (hub-select)string | undefined'body'下拉面板所附加到的元素的 CSS 选择器。默认为 'body',使面板得以逃离带有 overflow/transform 的祖先元素(卡片、滚动容器、模态框);传入 undefined 可将其内联渲染。
addTag (hub-select)boolean | ((term: string) => any | Promise<any>)false根据搜索词创建条目(dropdown 格式):true 按原样添加该词;函数则将该词映射为新条目,可同步或返回 Promise。
addTagText (hub-select)stringNgSelectConfig.addTagText启用 addTag 时,输入过程中显示的“添加条目”行的文案。
minTermLength (hub-select)number0触发筛选(或 typeahead Subject)之前搜索词的最小长度。
typeahead (hub-select)Subject<string> | undefinedundefined接收搜索词变化的 Subject,用于异步/服务端加载;一旦提供,客户端筛选即被关闭——请通过 items 回传结果。
compareWith (hub-select)((a: any, b: any) => boolean) | undefinedundefined条目与所绑定值之间的自定义相等判断(例如按 id 比较对象);省略时采用供应商内置的比较逻辑。
searchFn (hub-select)((term: string, item: any) => boolean) | undefinedundefined替换 `searchable` 所使用的内置匹配逻辑。它接收键入的搜索词和一个条目,并返回该条目是否匹配——因此搜索得以查看标签并未显示的字段。
mode (hub-datepicker)'single' | 'range' | 'day-time-range''single'单个日期、自由日期范围,或某一天内的开始与结束时间。
granularity (hub-datepicker)'year' | 'month' | 'day' | 'hour' | 'minute' | 'second''day'每个选定时间点所携带的精度,以及用于选取它的面板:year 和 month 渲染 12 格网格,day 渲染日历,hour、minute 和 second 则在日历下方增加时间栏。它与 mode 正交:mode 决定选取几个点,granularity 决定每个点的精度。默认值为 day,输出与以往完全相同的 YYYY-MM-DD 字符串;从 hour 起,值变为完整的 ISO 8601 时间戳,携带读者的本地时间以及该日期的时区偏移。
valueFormat / parse (hub-datepicker)'iso' | 'date' | 'timestamp' | ((date) => unknown) / ((raw) => Date | null) | null'iso' / null值的两个轴。valueFormat 决定绑定控件所持有的内容:'iso'(默认)、'date' 为原生 Date、'timestamp' 为纪元毫秒,或传入函数以应对其他情况。parse 决定传入值的读取方式,覆盖对任意宽度 ISO 字符串、Date 实例和纪元毫秒的内置识别——它同样作用于 min 与 max。
minuteStep / secondStep / hourFormat (hub-datepicker)number / number / '12' | '24' | undefined5 / 1 / undefined时间相关设置:minuteStep 与 secondStep 是微调按钮的步进值,hourFormat 强制使用 12 小时制或 24 小时制——未设置时由区域设置推导,并且同时作用于输入框显示与面板,因此两者绝不会相互矛盾。三者均回退到 provideHubForms 的全局配置。
min / max / disabledDates (hub-datepicker)string | Date | number | null / ((date: Date) => boolean) | nullnull可选范围与按日期禁用的谓词。范围会考虑时间而不仅是日期:只有当某一天没有任何时刻被允许时,该天才会被禁用,因此 min = 2026-09-01T14:00 仍让 9 月 1 日可点击,而由时间控件拒绝更早的时刻。接受 ISO 字符串、Date 或纪元毫秒。
locale / firstDayOfWeek / weekdayFormat (hub-datepicker)string / number / 'short' | 'narrow' | 'long'LOCALE_ID / undefined / undefined日历国际化:locale 是用于显示值及月份/星期名称的 BCP-47 标签(默认为应用的 LOCALE_ID,再回退到 en-US);firstDayOfWeek 设置每周的第一天(0 = 周日,1 = 周一……);weekdayFormat 决定星期表头的宽度。后两者会回退到全局的 provideHubForms 配置。
displayFormat / timeDisplayFormat / rangeSeparator / labels (hub-datepicker)Intl.DateTimeFormatOptions | string | ((date) => string) / Intl.DateTimeFormatOptions / string / Partial<HubDatepickerLabels>undefined / undefined / undefined / {}显示格式:displayFormat 渲染所选值,接受 Intl.DateTimeFormatOptions、形如 'dd/MM/yyyy HH:mm' 的 Angular 日期模式,或一个函数;一旦粒度携带时间,timeDisplayFormat 会叠加其上,因此日期部分仍保持 displayFormat 所指定的样子;rangeSeparator 是范围两个日期之间的文本;labels 按实例覆盖界面标签(合并于全局配置之上)。
clearable / showToday / closeOnSelect (hub-datepicker)booleantrue / true / true行为开关:clearable 显示清除快捷按钮,showToday 显示“今天”快捷按钮,closeOnSelect 在选定日期后关闭日历(仅单选模式)。默认值:true / true / true。
multiple (hub-file-input)booleanfalse是否可以持有多个文件。会将控件值从 File 切换为 File[]。
accept (hub-file-input)string'*'接受的文件类型,例如 image/*,.pdf。拖放和粘贴时同样生效,而不仅限于系统对话框。
maxSize / minSize / maxTotalSize (hub-file-input)number | nullnull单个文件的最大与最小大小,以及合计最大大小(字节)。
maxFiles (hub-file-input)number | nullnull文件数量上限。仅在配合 multiple 时有意义。
dragDrop / paste (hub-file-input)booleantrue是否可以将文件拖放到字段上,以及是否可以粘贴进来。
preview (hub-file-input)'none' | 'list' | 'grid''list'文件的呈现方式:不呈现、列表,或缩略图网格。
allowDuplicates (hub-file-input)booleanfalse是否允许两次选择同一个文件(以名称、大小和最后修改时间为键)。
capture (hub-file-input)'user' | 'environment' | nullnull在支持的平台上打开设备摄像头,而非文件浏览器。
autoUpload (hub-file-input)booleantrue新接受的文件是否立即开始上传。未注册上传器时会被忽略。
buttonLabel / hint (hub-file-input)string | nullnull覆盖浏览按钮文本以及自动生成的限制提示。
dropText / dropSubtext (hub-file-input)string | nullnull按实例覆盖拖放区的两行提示文本。两者均回退到全局标签。
classlist (every field except hub-segmented and hub-legend)string''应用于宿主元素的额外 CSS 类。
showValid (all fields)booleanHubFormsConfig.showValid有效的字段是否显示其有效状态。默认关闭,因为把每个尚未触碰的字段都涂成绿色的表单等于什么都没说;而无效状态始终会显示。
validFeedback (all fields)string | nullnull开启 `showValid` 时,字段变为有效后在其下方渲染的消息。
invalidFeedbackTemplateFn (all fields)((key: string, value: any) => string) | nullnull仅在此字段上覆盖指定错误键对应的消息。它接收错误键及其值并返回文本——应用级的默认实现位于 `provideHubForms`。
min / max (hub-input)number | undefined (two-way, model)undefinednumber 与 counter 格式的数值上下限。双向绑定,因此自行钳制取值的计数器会把该边界回报出来。
mode (hub-otp-input)'numeric' | 'alphanumeric' | 'alpha''numeric'每个输入框接受哪些字符,以及手机会弹出哪种键盘:仅数字,或字母与数字。
min / max (hub-timepicker)string (HH:MM)''字段所接受的最早与最晚时间,格式为 `HH:MM`。留空表示不设限制。
step (hub-timepicker)number (seconds)0原生步进器的粒度,以秒为单位。`0` 表示保留浏览器默认的一分钟。
group / groupName (form[hubForm], hub-fieldset)AbstractControl | null / string | undefinednull / undefined容器所呈现错误的目标分组。可以直接给 `group` 传入一个 `AbstractControl`,或者给 `groupName` 传入外层表单中某个子控件的名称——当容器本身已经包裹了它所报告的分组时,两者都不需要。
errorTrigger (form[hubForm], hub-fieldset)'touched' | 'submit' | 'always''touched'分组级错误何时变为可见:分组被触碰之后、仅在尝试提交之后,或立即显示。
formTextType (all fields)'bottom'辅助文字的位置。仅支持 `bottom`。
rows (hub-textarea)number可见的文本行数。
cols (hub-textarea)number可见的列数。设置后文本域不再拉伸至整宽。
maxlength (hub-textarea)number最大字符数。同时决定原生限制与计数器。
counter (hub-textarea)boolean是否在控件下方显示字符计数器。
autoresize (hub-textarea)boolean文本域是否随内容自动增高。
length (hub-otp-input)number验证码的单元格(字符)数量。
secret (hub-otp-input)boolean像密码一样遮蔽字符。
separator (hub-otp-input)string组与组之间显示的分隔符。
separatorEvery (hub-otp-input)number每 N 个单元格插入一个视觉分隔符(0 表示不插入)。
showValue (hub-slider)boolean是否在滑块上方显示数值气泡。
step (hub-input, hub-slider)number步进值(数字或计数器输入)。
legend (hub-fieldset)string图例文字。投影 `hubLegend` 模板时会被忽略。
required (all fields)boolean | null (two-way, model)null该字段是否为必填。在响应式绑定下,它由控件自身的校验器推导得出,因此直接内联设置只对模板驱动的字段生效;它决定必填星号与 `required` 属性。
required (hub-legend)boolean是否渲染必填指示符。
invalid (hub-legend)boolean是否渲染无效状态样式。

输出

响应 forms 的行为——有 13 个事件可供你挂接逻辑。

名称类型描述
valueChangeEventEmitter<value>每当字段值变化时触发。
search (hub-input)EventEmitter<string>用户输入时发出的防抖输入提示词(文本类输入)。
rejected (hub-file-input)EventEmitter<HubFileRejection[]>被声明的限制所拒绝的文件,每个都附带拒绝原因。
fileRemoved (hub-file-input)EventEmitter<File>从选择中移除的文件。
uploadStateChange (hub-file-input)EventEmitter<readonly HubFileItem[]>每当上传状态或进度变化时的完整条目列表。
submit (form[hubForm]) — the native eventSubmitEvent (native, not a custom output)并非自定义输出:`hubForm` 监听表单自身的 `submit` 事件,阻止默认的导航行为,将整棵控件树标记为已触碰,并翻转 submitted 状态。若需要自己的处理器,请在表单上绑定 `(submit)`。
disabledChange / requiredChange (all fields) · labelTypeChange / placeholderChange / minChange / maxChange / passwordRevealedChange (hub-input) · valueChange (hub-segmented)EventEmitter<T> (the paired half of each two-way model)每个双向的 `model()` 输入都会发布一个与之对应的 `Change` 输出,`[(disabled)]` 之类的写法才得以工作。之所以在此列出,是因为「香蕉盒」双向绑定语法把它们隐藏了起来。
opened / closed / cleared / viewChange (hub-datepicker)EventEmitter日历生命周期和导航事件。
onOpen / onClose / onClear / onSearch / onAdd / onRemove (hub-select)EventEmitter下拉框生命周期以及标签/自动补全事件。
onFocus / onBlur (hub-select)EventEmitter<any>当下拉控件获得或失去焦点时发出(dropdown 格式),转发供应商的 focus/blur 事件。
scroll / scrollToEnd (hub-select)EventEmitter<{ start: number; end: number }> / EventEmitter<any>scroll 在下拉列表滚动时发出可见的 { start, end } 窗口;scrollToEnd 在列表到达末尾时发出——这是配合 typeahead 实现无限/分页加载的挂钩。
enter (hub-input)EventEmitter<number | string | boolean | File | FileList | null>按下 Enter 时发出当前值。
completed (hub-otp-input)EventEmitter<string>所有单元格填满后发出完整验证码。

模板

打造你自己的样式——10 个模板插槽让你可以投影自定义标记。

名称描述示例
hubFormText投影丰富的辅助文本内容。<ng-template hubFormText>…</ng-template>
hubValidationError覆盖指定错误键的提示消息。<ng-template hubValidationError key="min">…</ng-template>
hubLegend自定义 fieldset 的 legend 内容。<ng-template hubLegend>…</ng-template>
ng-option-tmp (hub-select)自定义下拉选项渲染(重新导出的 ng-select 指令)。<ng-template ng-option-tmp let-item="item">…</ng-template>
hubFileIcon (hub-file-input)无缩略图文件的单文件图标;以隐式上下文接收该条目。<ng-template hubFileIcon let-item>…</ng-template>
hubFilePreview (hub-file-input)完全替换所选文件的渲染,并接收该条目以及移除、重试和取消操作。<ng-template hubFilePreview let-item let-remove="remove">…</ng-template>
hubFileDropzoneNotice (hub-file-input)在拖放区顶部、图标上方投影任意标记 —— 用于提示语和限制说明都无法表达的通知。<p hubFileDropzoneNotice>2 documents still missing</p>
hubSegmentedOption (hub-segmented)替换每个分段的内容(图标、徽章、富文本标记),组件仍负责选择、键盘导航与 ARIA。上下文:选项(隐式)、selected 与 index。<ng-template hubSegmentedOption let-option let-selected="selected" let-index="index">…</ng-template>
hubSelectSuffix (hub-select,已弃用)自 22.16.0 起弃用——请使用 [hubAppend],它在所有字段上都能做同样的事。它仍可继续使用;两者同时存在时以 [hubAppend] 为准。在下拉选择器的行末边缘附加一个可交互控件:一个作用于当前选中项的按钮——配置它、查询它、新建一个。它被声明为模板而非投影内容,因为选择器的通用 ng-content 负责把 ng-option 传给底层引擎,会把它一并吞掉;从模板渲染还能让操作在 DOM 中位于控件之后,因此 Tab 会先到达字段、再到作用于它的按钮。控件与操作共用一条边框,读起来是同一个字段。<ng-template hubSelectSuffix><button …>…</button></ng-template>
hubPrepend / hubAppend (all box-shaped fields)附加在字段边缘的内容,比 prepend / append 字符串能承载的更丰富:一个图标,或一个作用于该值的按钮。所有渲染为「装着值的框」的字段都支持——hub-input、hub-select、hub-textarea 和 hub-datepicker。它与字符串附加标签组合而非取代:字符串先渲染,因此投影内容始终位于该侧最外层——单位标注字段,操作位于其外。投影内容采用字段的边框、圆角与高度而非自身的,因此按钮不会在控件旁画出第二条更粗的接缝。之所以声明为模板,是因为字段的 ng-content 已另有用途。 插槽也可以放入另一个字段——hub-input、hub-select、hub-textarea 或 hub-datepicker 作为直接子元素——它会与宿主字段严丝合缝地相接,使价格与其计价周期读作它们本来就是的同一句话。<ng-template hubAppend><button …><hub-icon … /></button></ng-template>