ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Angular Material 自动完成组件 MatAutocomplete 完全指南:API 解析、源码原理与实战示例

Angular Material 自动完成组件 MatAutocomplete 完全指南:API 解析、源码原理与实战示例 Angular Material 自动完成组件 MatAutocomplete 完全指南API 解析、源码原理与实战示例【免费下载链接】componentsComponent infrastructure and Material Design components for Angular项目地址: https://gitcode.com/GitHub_Trending/co/components自动完成Autocomplete是 Angular Material 组件库中最常用的交互组件之一它由一个普通文本输入框与一个承载候选选项的下拉面板组合而成。本文以本仓库Component infrastructure and Material Design components for Angular中angular/material/autocomplete的官方 API 报告 goldens/material/autocomplete/index.api.md 为主线骨架结合 组件使用文档 与 核心源码、触发器源码系统讲解该组件的公开 API 面、底层实现机制、完整配置项与可运行的实战代码。读完本文你将能够从零搭建带过滤、带分组、可定制挂载位置的自动完成输入框并理解其键盘交互、无障碍支持与事件模型背后的实现原理。一、组件家族总览从 API 报告看整体架构根据 API 报告angular/material/autocomplete包对外暴露的公开 API 由一个 NgModule 和若干组件、指令、注入令牌、事件类与函数组成它们协同工作构成了完整的自动完成能力API 类型名称职责NgModuleMatAutocompleteModule聚合模块同时依赖并再导出OverlayModule、MatOptionModule、BidiModule、CdkScrollableModule组件MatAutocomplete选项面板本身选择器mat-autocomplete可导出matAutocomplete指令MatAutocompleteTrigger绑定在input[matAutocomplete]/textarea[matAutocomplete]上的触发器指令MatAutocompleteOrigin指定面板的连接锚点元素选择器[matAutocompleteOrigin]组件MatOption单个选项来自../core由 public-api.ts 再导出组件MatOptgroup选项分组同样来自../core注入令牌MAT_AUTOCOMPLETE_DEFAULT_OPTIONS覆盖全局默认配置注入令牌MAT_AUTOCOMPLETE_SCROLL_STRATEGY面板打开期间的滚动策略注入令牌MAT_AUTOCOMPLETE_VALUE_ACCESSOR将触发器注册为ControlValueAccessor的 provider事件类MatAutocompleteSelectedEvent选项被选中时触发携带source与option事件接口MatAutocompleteActivatedEvent活动选项变化时触发携带source与option可为null配置接口MatAutocompleteDefaultOptions全局默认选项的类型定义函数getMatAutocompleteMissingPanelError()生成“找不到面板实例”错误从依赖关系看该组件深度复用 CDK 基础设施angular/cdk/overlay负责面板浮层定位、angular/cdk/a11y的ActiveDescendantKeyManager负责键盘焦点管理、angular/cdk/scrolling负责滚动容器、angular/cdk/bidi负责双向文本方向同时通过ControlValueAccessor与angular/forms的表单体系无缝集成见 autocomplete-module.ts 与 autocomplete-trigger.ts 中的模块声明。二、快速上手搭建第一个自动完成输入框使用前先在模块或独立组件中引入MatAutocompleteModule。以下为官方autocomplete-simple示例源码位于 autocomplete-simple-example.ts 与其 模板。组件类import {Component} from angular/core; import {FormControl, FormsModule, ReactiveFormsModule} from angular/forms; import {MatAutocompleteModule} from angular/material/autocomplete; import {MatInputModule} from angular/material/input; import {MatFormFieldModule} from angular/material/form-field; Component({ selector: autocomplete-simple-example, templateUrl: autocomplete-simple-example.html, styleUrl: autocomplete-simple-example.css, imports: [ FormsModule, MatFormFieldModule, MatInputModule, MatAutocompleteModule, ReactiveFormsModule, ], }) export class AutocompleteSimpleExample { myControl new FormControl(); options: string[] [One, Two, Three]; }模板form classexample-form mat-form-field classexample-full-width mat-labelNumber/mat-label input typetext placeholderPick one aria-labelNumber matInput [formControl]myControl [matAutocomplete]auto mat-autocomplete #automatAutocomplete for (option of options; track option) { mat-option [value]option{{option}}/mat-option } /mat-autocomplete /mat-form-field /form两个关键步骤定义面板用mat-autocomplete标签创建面板内部用mat-option定义每个选项[value]决定该选项被选中后写入输入框/表单的值绑定触发器通过exportAs把面板实例导出到局部模板变量此处为#auto再绑定到输入框的matAutocomplete输入属性上。该属性的对应实现是MatAutocompleteTrigger.autocompleteInput(matAutocomplete)源码位于 autocomplete-trigger.ts。组件类中用ReactiveFormsModule的FormControl跟踪输入值。文档也提示如果偏好模板驱动表单同样可行只是响应式表单更便于订阅值变化。三、实现过滤基于 valueChanges 的自定义过滤器面板默认在聚焦时可开合、选项可选中但“边输入边过滤”需要自行实现。官方autocomplete-filter示例见 autocomplete-filter-example.ts演示了标准做法export class AutocompleteFilterExample { myControl new FormControl(); options: string[] [One, Two, Three]; filteredOptions: Observablestring[]; constructor() { this.filteredOptions this.myControl.valueChanges.pipe( startWith(), map(value this._filter(value || )), ); } private _filter(value: string): string[] { const filterValue value.toLowerCase(); return this.options.filter(option option.toLowerCase().includes(filterValue)); } }模板中把filteredOptions通过async管道交给mat-option列表mat-autocomplete #automatAutocomplete for (option of filteredOptions | async; track option) { mat-option [value]option{{option}}/mat-option } /mat-autocomplete要点解析startWith()的作用用空字符串“预热”值变化流使组件在初始化时尚未发生任何输入就按空串执行一次过滤从而保证面板在聚焦时即可显示全部选项过滤器完全自定义只要返回MatOption的候选值数组即可不限于字符串前缀匹配——可以是对象、数组或任意可比较结构无障碍提醒官方文档特别建议若使用非标准过滤规则不限于从字符串开头匹配应在页面上补充说明过滤条件的文字提示这对使用屏幕阅读器的用户尤其重要。四、分离控件值与显示值displayWith 的妙用默认情况下mat-option的[value]既作为表单保存的控件值也作为输入框中显示的文本。当两者需要不同时典型场景表单保存对象而输入框只展示其中一个字符串属性使用MatAutocomplete的displayWith输入属性。官方autocomplete-display示例见 autocomplete-display-example.tsexport interface User { name: string; } export class AutocompleteDisplayExample { myControl new FormControlstring | User(); options: User[] [{name: Mary}, {name: Shelley}, {name: Igor}]; filteredOptions: ObservableUser[]; constructor() { this.filteredOptions this.myControl.valueChanges.pipe( startWith(), map(value { const name typeof value string ? value : value?.name; return name ? this._filter(name as string) : this.options.slice(); }), ); } displayFn(user: User): string { return user user.name ? user.name : ; } private _filter(name: string): string[] { const filterValue name.toLowerCase(); return this.options.filter(option option.name.toLowerCase().includes(filterValue)); } }模板中绑定[displayWith]displayFnmat-autocomplete #automatAutocomplete [displayWith]displayFn for (option of filteredOptions | async; track option) { mat-option [value]option{{option.name}}/mat-option } /mat-autocomplete实现细节displayWith在MatAutocomplete上定义为Input() displayWith: ((value: any) string) | null null见 autocomplete.ts。过滤器中的typeof value string ? value : value?.name判断是必须的——因为当用户回删选中值、输入框里只剩纯字符串时valueChanges发出的就是字符串而非User对象。五、强制选择requireSelection 与全局默认配置默认情况下自动完成接受用户随意输入的任何文本。若业务要求“必须从候选中选中一项”可开启requireSelection输入。其行为源码注释见 autocomplete.ts有两方面用户打开面板、改变了输入值但未选择任何选项便离开时值会被重置为null用户打开面板又关闭、且未改动值则保留旧值。mat-autocomplete #automatAutocomplete requireSelection ... /mat-autocomplete该行为可以全局统一配置。MAT_AUTOCOMPLETE_DEFAULT_OPTIONS注入令牌在源码中providedIn: root并带有默认工厂见 autocomplete.tsexport const MAT_AUTOCOMPLETE_DEFAULT_OPTIONS new InjectionTokenMatAutocompleteDefaultOptions( mat-autocomplete-default-options, { providedIn: root, factory: () ({ autoActiveFirstOption: false, autoSelectActiveOption: false, hideSingleSelectionIndicator: false, requireSelection: false, hasBackdrop: false, }), }, );MatAutocompleteDefaultOptions接口同样见 autocomplete.ts支持的全部键为配置项类型默认值说明autoActiveFirstOptionbooleanfalse面板打开时是否高亮第一个选项autoSelectActiveOptionbooleanfalse键盘导航过程中是否自动选中当前活动选项requireSelectionbooleanfalse是否强制用户必须做出选择backdropClassstring—应用到遮罩层backdrop的 CSS 类hasBackdropbooleanfalse面板打开时是否显示遮罩层overlayPanelClassstring \| string[]—应用到浮层面板的 CSS 类可多个hideSingleSelectionIndicatorbooleanfalse单选时是否隐藏选中指示图标应用级覆盖方式例如在 providers 中providers: [ { provide: MAT_AUTOCOMPLETE_DEFAULT_OPTIONS, useValue: {autoActiveFirstOption: true, requireSelection: true}, }, ],从源码可以看到组件构造器中正是用这些默认值初始化各输入属性this.autoActiveFirstOption !!this._defaults.autoActiveFirstOption因此组件级输入可以逐项覆盖全局配置见 autocomplete.ts 构造函数部分。六、键盘交互与焦点管理官方文档给出完整的键盘交互约定快捷键行为↓Down Arrow移动到下一个选项↑Up Arrow移动到上一个选项Enter选中当前活动选项Escape关闭面板Alt↑关闭面板Alt↓存在匹配选项时打开面板这些行为在底层由ActiveDescendantKeyManager实现。面板组件在ngAfterContentInit中创建键盘管理器见 autocomplete.tsthis._keyManager new ActiveDescendantKeyManagerMatOption(this.options) .withWrap() // 支持首尾循环 .skipPredicate(this._skipPredicate);值得注意的实现细节_skipPredicate恒返回false即不跳过禁用选项。源码注释引用了 WAI-ARIA APG 键盘接口规范——对于 listbox 这类复合控件禁用的选项仍应可被键盘聚焦但不可点击这与普通规则“禁用元素移出 Tab 序”形成例外见 autocomplete.ts 的_skipPredicate注释。与之配套的两个输入属性autoActiveFirstOption打开面板即高亮第一个选项适用于候选较少、希望用户直接回车选中的场景autoSelectActiveOption在键盘上下导航过程中活动选项的值被“自动选中”但暂不写入模型直到面板关闭才落库触发器端通过_pendingAutoselectedOption与_valueBeforeAutoSelection跟踪此状态见 autocomplete-trigger.ts。七、触发器深入位置、禁用、滚动策略与常见错误MatAutocompleteTrigger是连接输入框与面板的枢纽其选择器为input[matAutocomplete], textarea[matAutocomplete]并通过MAT_AUTOCOMPLETE_VALUE_ACCESSOR基于NG_VALUE_ACCESSOR实现ControlValueAccessor见 autocomplete-trigger.ts因此可无缝配合FormControl、[(ngModel)]及formControlName。它的主要输入与公开成员成员绑定别名类型/默认值说明autocompletematAutocompleteMatAutocomplete关联的面板实例positionmatAutocompletePositionauto \| above \| below默认autoauto优先在下方展开视口空间不足时自动翻转到上方above/below强制固定方向connectedTomatAutocompleteConnectedToMatAutocompleteOrigin面板的定位锚点默认是触发器本身autocompleteAttributeautocompleteoff透传给原生输入框的autocomplete属性autocompleteDisabledmatAutocompleteDisabledboolean默认false禁用后输入框退化为普通输入框无法打开面板panelOpen—getterboolean面板当前是否打开activeOption—getterMatOption \| null当前活动选项optionSelections—ObservableMatOptionSelectionChange选项选中流panelClosingActions—ObservableMatOptionSelectionChange \| null面板关闭动作流openPanel()/closePanel()/updatePosition()—方法编程式控制面板开关与重定位几点实现层面的细节宿主 ARIA 属性自动管理触发器通过 host 绑定动态维护rolecombobox、aria-autocompletelist、aria-expanded、aria-controls、aria-haspopuplistbox、aria-activedescendant等属性且全部在autocompleteDisabled时置空见 autocomplete-trigger.ts 的host定义滚动策略可替换MAT_AUTOCOMPLETE_SCROLL_STRATEGY令牌默认返回createRepositionScrollStrategy面板随页面滚动重新定位若需要固定面板或自定义行为可注入该令牌提供自己的() ScrollStrategy常见错误getMatAutocompleteMissingPanelError()会在“尝试打开一个不存在的mat-autocomplete实例”时被抛出例如matAutocomplete绑定写错、或试图在ngAfterContentInit钩子之前打开面板——错误信息会提示核对传入的 id 与打开时机。八、灵活挂载自定义输入元素与改变面板锚点8.1 脱离 mat-form-field 的自定义输入matAutocomplete并不强制要求宿主是mat-form-field。任何input/textarea元素都可以直接挂载触发器从而完全自定义输入框外观input typetext [matAutocomplete]auto placeholderType here mat-autocomplete #automatAutocomplete for (option of options; track option) { mat-option [value]option{{option}}/mat-option } /mat-autocomplete官方autocomplete-plain-input示例演示了该用法适合不想引入mat-form-field全部能力、只想使用自动完成交互的场景。8.2 把面板挂到其他元素matAutocompleteOrigin matAutocompleteConnectedTo默认面板以输入框为锚点。如需挂载到容器元素例如自定义包装 div用matAutocompleteOrigin指令标记锚点再通过matAutocompleteConnectedTo指向它div classcustom-wrapper-example matAutocompleteOrigin #originmatAutocompleteOrigin input matInput [formControl]myControl [matAutocomplete]auto [matAutocompleteConnectedTo]origin /div mat-autocomplete #automatAutocomplete for (option of options; track option) { mat-option [value]option{{option}}/mat-option } /mat-autocompleteMatAutocompleteOrigin是一个极简指令仅暴露自身的ElementRefHTMLElement作为连接点见 autocomplete-origin.tsconnectedTo输入则指向该指令实例。8.3 面板宽度与外观控制MatAutocomplete还提供以下与外观相关的输入panelWidth任意 CSS 宽度值如300px或50未设置时面板与宿主同宽class输入别名将宿主元素上的类透传到浮层面板内部便于直接为面板写样式disableRipple禁用面板内选项的水波纹反馈hideSingleSelectionIndicator隐藏单选时的对勾指示详见下节无障碍说明。九、选项分组mat-optgroup当选项数量多、需要分层展示时用mat-optgroup对mat-option分组官方autocomplete-optgroup示例位于 src/components-examples/material/autocomplete/autocomplete-optgroup/mat-autocomplete #automatAutocomplete mat-optgroup labelGroup name mat-option valueitemItem/mat-option /mat-optgroup /mat-autocompleteMatOptgroup支持label组标题与disabled整组禁用。面板组件通过ContentChildren(MAT_OPTGROUP, {descendants: true}) optionGroups收集分组通过ContentChildren(MatOption, {descendants: true}) options收集全部选项见 autocomplete.ts。源码中还包含一个平台特判在 Safari 上inertGroups会被置为true见构造函数用以规避 VoiceOver 朗读分组时的已知缺陷。十、无障碍Accessibility设计MatAutocomplete实现了 ARIA combobox 交互模式这是其无障碍设计的核心输入触发器承担rolecombobox弹出内容承担rolelistbox见面板模板 autocomplete.html不要在选项内嵌套交互控件由于 listbox 模式选项内部不应再放按钮、复选框等其他可交互元素否则会干扰绝大多数辅助技术必须提供可访问标签可通过mat-form-field内的mat-label、原生label、aria-label或aria-labelledby任一方式给出焦点保持在输入框面板打开时焦点始终留在触发输入框通过aria-activedescendant指向当前活动选项的 id 来支持选项间导航面板 id 由_IdGenerator生成mat-autocomplete-前缀的唯一值见 autocomplete.ts选中指示默认面板用对勾标识已选项。官方文档明确指出虽然可用hideSingleSelectionIndicator隐藏对勾但这会降低无障碍性——视觉用户更难甚至无法分辨当前选中项建议仅在确有设计需求时使用。十一、事件模型与编程控制MatAutocomplete对外暴露四个事件定义见 autocomplete.ts事件载荷触发时机optionSelectedMatAutocompleteSelectedEvent含source与option用户选定一个选项openedvoid面板打开closedvoid面板关闭optionActivatedMatAutocompleteActivatedEvent含source与option可为null活动选项变化面板打开期间典型用法mat-autocomplete #automatAutocomplete (optionSelected)onSelected($event) (opened)onOpened() (closed)onClosed() ... /mat-autocompleteonSelected(event: MatAutocompleteSelectedEvent) { // event.source 为面板实例event.option 为被选中的 MatOption console.log(selected:, event.option.value); }与此同时触发器提供optionSelectionsObservable 与panelClosingActionsObservable 用于更底层的流式监听openPanel()、closePanel()、updatePosition()三个方法让业务代码可以精确控制面板的开关与重定位例如在窗口尺寸变化时手动updatePosition()不过触发器本身已订阅ViewportRuler与BreakpointObserver自动处理了大部分场景见 autocomplete-trigger.ts。附录核心 API 速查源自 API 报告以下速查依据 goldens/material/autocomplete/index.api.md 整理供快速引用MatAutocompleteModule导入该模块即可使用mat-autocomplete、matAutocomplete触发器、matAutocompleteOrigin并自动获得MatOptionModule与 CDK overlay/bidi/scrolling 能力MatAutocomplete选择器mat-autocomplete导出名matAutocomplete输入含aria-label、aria-labelledby、displayWith、autoActiveFirstOption、autoSelectActiveOption、requireSelection、panelWidth、disableRipple、class、hideSingleSelectionIndicator输出含optionSelected、opened、closed、optionActivated另有只读成员isOpen、panel、options、optionGroups、templateMatAutocompleteTrigger选择器input[matAutocomplete], textarea[matAutocomplete]输入matAutocomplete、matAutocompletePosition、matAutocompleteConnectedTo、autocomplete原生属性透传、matAutocompleteDisabledMatAutocompleteOrigin选择器[matAutocompleteOrigin]导出名matAutocompleteOrigin令牌MAT_AUTOCOMPLETE_DEFAULT_OPTIONS、MAT_AUTOCOMPLETE_SCROLL_STRATEGY、MAT_AUTOCOMPLETE_VALUE_ACCESSOR相关测试与更多示例组件行为可参考 autocomplete.spec.ts其余示例分布在 src/components-examples/material/autocomplete/ 下的autocomplete-require-selection、autocomplete-auto-active-first-option、autocomplete-plain-input、autocomplete-optgroup、autocomplete-harness等目录中可作为从简单到进阶的完整学习序列。【免费下载链接】componentsComponent infrastructure and Material Design components for Angular项目地址: https://gitcode.com/GitHub_Trending/co/components创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表