- UI组件
- 前端
【免费下载链接】ng-zorro-antd
Angular UI Component Library based on Ant Design
导读
在使用 NG-ZORRO 的nz-select时,经常会遇到一个看似矛盾的需求:表单需要显示一个默认值,但这个默认值并不存在于下拉选项列表中(例如来自后端历史数据、临时占位值,或编辑场景下已下线的选项)。如果强行把它加进选项列表,用户会看到一个多余甚至无法选择的选项;不加,默认值又无法渲染。本篇基于 components/select/demo/default-value.md 及其配套示例,讲解如何借助nz-option的nzHide属性,让默认值既能正确回显、又不会出现在下拉面板中,并深入到源码层面说明其过滤原理。
场景与需求本质
官方演示文档给出了一句精炼的说明(default-value.md):
当需要显示默认值,同时默认值又不在选项列表中时,可以使用
nzHide在nz-option中将默认选项隐藏。
即核心诉求是两个状态分离:
- 已选中态(顶部显示区):默认值必须能正常渲染成标签(tag)或选中文本;
- 下拉面板(选项列表):默认值对应的选项不应出现在列表中,避免用户重复选择或误以为它是候选值。
nzHide正是为这种"值参与选中、但不参与候选"的选项设计的。
核心 API:nz-option的nzHide
nz-option的完整属性表见 components/select/doc/index.en-US.md,其中与本文相关的属性定义如下:
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
[nzLabel] | 在nz-select和下拉菜单中显示的文本 | string \| number | - |
[nzValue] | 传给nz-select的ngModel的值 | any | - |
[nzHide] | 是否在选项列表中隐藏该选项 | boolean | false |
在源码 components/select/option.component.ts 中,nzHide通过booleanAttribute转换器声明:
@Input({ transform: booleanAttribute }) nzDisabled = false; @Input({ transform: booleanAttribute }) nzHide = false; @Input({ transform: booleanAttribute }) nzCustomContent = false;这意味着模板中既可以写nzHide(属性存在即为true),也可以写[nzHide]="someCondition"进行动态绑定。
完整示例:两个典型场景
配套示例源码位于 components/select/demo/default-value.ts,覆盖了多选与单选两种模式,是官方推荐的标准写法:
import { Component, signal } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { NzSelectModule } from 'ng-zorro-antd/select'; @Component({ selector: 'nz-demo-select-default-value', imports: [FormsModule, NzSelectModule], template: ` <nz-select nzMode="multiple" nzPlaceHolder="Inserted are removed" [(ngModel)]="listOfSelectedValue"> @for (option of listOfOption; track option) { <nz-option [nzLabel]="option" [nzValue]="option" /> } @for (option of defaultOption; track option) { <nz-option [nzLabel]="option" [nzValue]="option" nzHide /> } </nz-select> <br /> <br /> <nz-select [(ngModel)]="value"> @for (option of listOfOption; track option) { <nz-option [nzLabel]="option" [nzValue]="option" /> } <nz-option nzLabel="Default Value" nzValue="Default" nzHide /> </nz-select> `, styles: ` nz-select { width: 100%; } ` }) export class NzDemoSelectDefaultValueComponent { readonly listOfOption = ['Option 01', 'Option 02']; readonly listOfSelectedValue = signal(['Default 01', 'Default 02']); readonly value = signal('Default'); get defaultOption(): string[] { return this.listOfSelectedValue(); } }场景一:多选(nzMode="multiple")
- 常规候选
Option 01、Option 02通过@for渲染为普通nz-option; ngModel初始值为['Default 01', 'Default 02'],这两个值不在候选列表中;- 通过第二个
@for再渲染一组nz-option,标签和值与默认值完全一致,但加上nzHide属性,使其只负责"占位供选中回显",不进入下拉面板。
此时界面上会呈现两个默认标签,而打开下拉面板时,Default 01、Default 02不会出现。
场景二:单选(默认模式)
单选场景更加直观:在常规选项之后追加一个<nz-option nzLabel="Default Value" nzValue="Default" nzHide />。ngModel初始值为字符串'Default',组件会在所有选项(含隐藏项)中匹配到该值并显示其nzLabel,但用户打开下拉列表时看不到这条"默认值"选项。
注意事项:placeholder 的语义
示例中多选设置了占位符nzPlaceHolder="Inserted are removed"("插入的会被移除"),它传达了一个行为提示:隐藏选项不参与候选匹配,通过输入/搜索插入的、与隐藏项无关的文本不会进入选中集合。占位符只在ngModel为空时显示,一旦隐藏默认值被选中,占位符即消失。
源码原理:隐藏选项如何被过滤
从源码结构看,nzHide的过滤逻辑分为两条路径,最终都汇聚在 components/select/select.component.ts 的updateListOfContainerItem()方法中。
1. 模板驱动(<nz-option>)路径
ngAfterContentInit()中(select.component.ts),组件会收集所有nz-option实例,把nzLabel、nzValue、nzHide等属性逐一映射为内部选项项,存为listOfTagAndTemplateItem。随后在构建下拉面板容器列表时:
let listOfContainerItem = this.listOfTagAndTemplateItem .filter(item => !item.nzHide) .filter(item => { if (!this.nzServerSearch && this.searchValue) { return this.nzFilterOption(this.searchValue, item); } else { return true; } });(见 select.component.ts)
可见隐藏项在第一步就被剔除,之后才会执行搜索过滤、激活项计算与分组标签插入。这意味着nzHide选项绝不会出现在下拉面板中,也不会被键盘上下键选中。
2. 已选中标签的渲染
关键点在于:隐藏选项虽然被从"容器列表"(下拉面板)过滤掉,但仍保留在listOfTagAndTemplateItem全量集合中。ngOnInit()中通过combineLatest([listOfValue$, listOfTemplateItem$])订阅(select.component.ts),把ngModel的当前值逐一在全量集合中按compareWith匹配,生成listOfTopItem用于顶部显示区渲染。因此隐藏选项既能以标签/文本形式正常回显,又不会进入下拉候选,两个状态互不干扰。
3. 响应式数据驱动([nzOptions])路径
若你更习惯用[nzOptions]传入选项数组而非模板标签,隐藏能力同样存在。NzSelectOptionInterface中定义了hide?: boolean字段(components/select/select.types.ts),在ngOnChanges()转换时被映射为内部nzHide:
const listOfTransformedItem = listOfOptions.map(item => { return { ... nzHide: item.hide || false, ... }; });(见 select.component.ts)
因此两种数据提供方式都能利用隐藏特性:
listOfOptions = signal([ { label: 'Option 01', value: 'Option 01' }, { label: 'Option 02', value: 'Option 02' }, { label: 'Default 01', value: 'Default 01', hide: true } ]);测试用例中的佐证
在 components/select/select.spec.ts 的测试组件中,nz-option的[nzHide]="o.nzHide"被作为标准属性参与组件渲染与交互验证;数据驱动模式下同样通过NzSelectItemInterface携带nzHide字段。这从测试层面印证了"隐藏选项作为一等公民参与选中、但不参与候选"的行为契约。
延伸:动态隐藏与清除默认值
nzHide支持动态绑定(booleanAttribute转换),因此可以按状态实时决定是否隐藏。仓库中另一个相关示例 components/select/demo/hide-selected.ts 展示了反向用法——把已选中的选项动态隐藏:
<nz-option [nzLabel]="option" [nzValue]="option" [nzHide]="isSelected(option)" />其原理与默认值场景完全一致:已选中的选项从下拉面板中消失,避免用户重复选择;取消选中后又恢复显示。这也是nzHide最具实用价值的设计——它把"选中状态"与"候选可见性"解耦,开发者可以自由组合出默认值回显、禁止重复选择、根据条件屏蔽某些选项等交互。
此外需要留意的是:隐藏选项虽然不可在下拉面板中点击选择,但允许通过ngModel初始值注入选中态;一旦用户在多选模式下点击标签的删除按钮删除该默认值,onItemDelete()会将其从listOfValue中移除(select.component.ts),之后由于它不在候选列表中,用户便无法再手动选回——除非重新设置默认值或调整nzHide条件,这一点在业务设计中应提前考虑。
小结
nzHide是 NG-ZORRO Select 在处理"默认值不在选项列表"这一常见表单场景时的官方解法,只需在nz-option上加一个布尔属性即可实现:
- 回显不失效:隐藏选项仍参与
ngModel值匹配,正常渲染标签与选中文本; - 候选不污染:隐藏选项在
updateListOfContainerItem()中被先行过滤,不出现在下拉面板与键盘导航中; - 两种写法通用:模板
nz-option nzHide与数据驱动nzOptions中的hide: true均可使用; - 动态可控:
booleanAttribute转换使其支持按业务条件实时开合隐藏。
在实际项目中,该方案尤其适用于编辑页回显历史数据、展示已失效/已下线的历史选项、以及"禁止重复选择"类交互,是 Select 组件高价值、低成本的一个隐藏能力。
- UI组件
- 前端
【免费下载链接】ng-zorro-antd
Angular UI Component Library based on Ant Design
相关推荐
告别"属性不存在"错误:TypeScript可选属性与默认值的优雅实践
告别"属性不存在"错误:TypeScript可选属性与默认值的优雅实践 你是否还在为TypeScript对象属性的"可能未定义"错误烦恼?是否经常在访问对象属性
编程语言编译器开发工具PPT Master 快速上手:三步把任意文档变成原生可编辑的 PowerPoint
PPT Master 快速上手:三步把任意文档变成原生可编辑的 PowerPoint 一份 PDF 进去,一个原生可编辑的 .pptx 出来:开源工具 PPT
AI 技能人工智能AI 应用Refine 中 useSelect 的 defaultValue 全面解析:让默认选项稳定出现在下拉列表中的完整方案
Refine 中 useSelect 的 defaultValue 全面解析:让默认选项稳定出现在下拉列表中的完整方案 defaultValue 是 Refin
前端企业应用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考