【发布时间】:2018-10-28 09:13:09
【问题描述】:
使用 MAT_AUTOCOMPLETE_DEFAULT_OPTIONS 注入令牌或 const AUTOCOMPLETE_OPTION_HEIGHT 自定义 mat-autocomplete 的方法是什么。这些常量等在公共 API here 中公开,但没有关于如何使用它们的文档
【问题讨论】:
使用 MAT_AUTOCOMPLETE_DEFAULT_OPTIONS 注入令牌或 const AUTOCOMPLETE_OPTION_HEIGHT 自定义 mat-autocomplete 的方法是什么。这些常量等在公共 API here 中公开,但没有关于如何使用它们的文档
【问题讨论】:
将MAT_AUTOCOMPLETE_DEFAULT_OPTIONS 添加到模块的providers 数组中,如下所示:
providers: [
// ...
{provide: MAT_AUTOCOMPLETE_DEFAULT_OPTIONS, useValue: {autoActiveFirstOption: false}}
]
至于其他常量,我不确定您是否可以调整它们。您可能不得不使用 CSS 样式,例如查看 this issue 以调整面板高度。
【讨论】:
这很奇怪,为什么像项目(选项)的高度这样需要的选项没有定义为输入。
因为不更改 AUTOCOMPLETE_OPTION_HEIGHT 我们会得到一个错误 (https://github.com/angular/components/issues/18030)
这是一个可能的解决方案:
步骤 1. 改变风格。这是最轻松的时刻。我们可以改变全局样式。让我们用 24px 代替 48px
mat-option.mat-option{
position: relative;
height: 24px!important;
line-height: 24px!important;
max-height: 24px!important;
}
步骤 2. 覆盖 MatAutocompleteTrigger 的原始 _scrollToOption 方法
痛点在这里:https://github.com/angular/components/blob/49a1324acc05cec1c5ff28d729abfe590f6772dd/src/material/autocomplete/autocomplete-trigger.tsline 498,方法_scrollToOption。
此方法采用两个硬编码常量(AUTOCOMPLETE_OPTION_HEIGHT、AUTOCOMPLETE_PANEL_HEIGHT)并使用它来计算新的滚动位置。当然,如果你没有 48px,但或多或少 - 它将无法正常工作。
所以,我们必须覆盖这个方法。
最优雅的方法 - 使用Directive(请记住,我们可以使用@ViewChild() 访问MatAutocompleteTrigger 并在父组件的范围内更改它,但这不是可重用的解决方案) .
import { Directive } from '@angular/core';
import { Host, Self, Optional, Input, OnInit } from '@angular/core';
import { MatAutocompleteTrigger, AUTOCOMPLETE_OPTION_HEIGHT, AUTOCOMPLETE_PANEL_HEIGHT } from '@angular/material';
import {
_countGroupLabelsBeforeOption,
_getOptionScrollPosition
} from '@angular/material/core';
@Directive({
selector: '[matAutocompleteTriggerAccessor]',
})
export class DirectiveAccessor implements OnInit {
@Input() optionHeight: number = AUTOCOMPLETE_OPTION_HEIGHT;
@Input() panelHeight: number = AUTOCOMPLETE_PANEL_HEIGHT;
constructor(
@Host() @Self() @Optional() public _refTrigger: MatAutocompleteTrigger
) { }
public ngOnInit() {
if (this._refTrigger === undefined || this._refTrigger === null) {
return;
}
this._refTrigger['_scrollToOption'] = this._scrollToOption.bind(this._refTrigger, this.optionHeight, this.panelHeight);
}
private _scrollToOption(
this: MatAutocompleteTrigger,
optionHeight: number,
panelHeight: number,
): void {
const index = this.autocomplete._keyManager.activeItemIndex || 0;
const labelCount = _countGroupLabelsBeforeOption(
index,
this.autocomplete.options,
this.autocomplete.optionGroups
);
if (index === 0 && labelCount === 1) {
this.autocomplete._setScrollTop(0);
} else {
const newScrollPosition = _getOptionScrollPosition(
index + labelCount,
optionHeight,
this.autocomplete._getScrollTop(),
panelHeight
);
this.autocomplete._setScrollTop(newScrollPosition);
}
}
}
_scrollToOption 方法的“原始”代码。我们只做一件事——避免使用常量:AUTOCOMPLETE_OPTION_HEIGHT、AUTOCOMPLETE_PANEL_HEIGHT
optionHeight 和 panelHeight 而不是这些常量
AUTOCOMPLETE_OPTION_HEIGHT、AUTOCOMPLETE_PANEL_HEIGHT 的值
现在我们可以修改我们的模板并添加新指令和添加输入。
<form class="example-form">
<mat-form-field class="example-full-width">
<input type="text" placeholder="Pick one" aria-label="Number" matInput [formControl]="myControl" [matAutocomplete]="auto" matAutocompleteTriggerAccessor [optionHeight]="24">
<mat-autocomplete #auto="matAutocomplete">
<mat-option *ngFor="let option of options" [value]="option">
{{option}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
</form>
注意。我们的指令matAutocompleteTriggerAccessor 和输入optionHeight 应该附加到<input>,而不是<mat-autocomplete>。
仅此而已。现在一切正常。
这是一个完整的解决方案:https://stackblitz.com/edit/angular-cn4ox8
【讨论】: