angular - 如何从函数中以编程方式调用 mat-options?
问题描述
我需要在 mat-select 组件上实现对双击事件的处理。这个想法是能够在双击事件上调用函数,但在单击事件上保持正常行为。通常这是不可能的,因为 mat-select 立即显示 mat-options 不允许检测到双击事件。
如果我尝试使用 setTimeOut 添加一些延迟,例如在触发 mat-select 时,mat-options 弹出窗口会立即显示。我找到了一种解决方法,因此我可以通过从一开始使用 [disabled] 禁用 mat-select 来双击 mat-select,这样我可以在不显示 mat-options 的情况下检测到 mat-select 的双击,但是当我尝试启用 mat 时- 从我的 singleClick() 函数中再次选择并再次显示 mat-options 弹出窗口。我不能,因为在我再次单击组件之前,angular 不会呈现新的更改。
理想情况下,我想在我的 mat-select 上单击一下,调用我的 singleClick() 函数,然后使用 [disabled]="false" 再次启用我的 mat-select,最后一次渲染组件,但角度检测只有更改,并且仅在下一次单击交互时才呈现组件。
我想做的是通过调用我的 singleClick() 函数来显示垫选项。有什么方法可以从我的 singleClick 函数中以编程方式调用 mat-options 吗?我希望你能给我一些建议,或者在这种情况下处理双击事件的更好方法。代码示例
这是我的组件:
<mat-select placeholder="Double click posible, single click not showing options until second time clicked" [disabled]="disableMatSelect"
(click)="singleClick($event)" (dblclick)="doubleClick()" (openedChange)="openedChange($event)" [(value)]="selected">
<mat-option *ngFor="let option of options" [value]="option.value">
{{ option.viewValue }}
</mat-option>
</mat-select>
这是我要调用 mat-options 弹出窗口的函数:
singleClick(event) {
this.isSingleClick = true;
setTimeout(() => {
if (this.isSingleClick && event.type == 'click') {
this.disableMatSelect = false;
//Here I would like to call for mat-options popup
this.clickEvent = 'Single Click';
}
}, 250);
}
解决方案
我首先尝试过preventDefault()
,但这没有用。所以我想出了这个解决方法,不是最好的,但它可能会为你指明正确的方向。
我创建了一个不可见的覆盖层来收听点击,然后我
stopPropagation()
就这样点击永远不会到垫选择。我听一下点击,如果里面
setTimeout()
我们没有第二次点击,然后用.open()
方法打开mat,这个可以通过“查看孩子”找到,@ViewChild('matSelect') matSelect: MatSelect;
然后this.matSelect.open()
如果我们再次单击,则转到该
doubleClick()
方法。
在那里你的stackblitz,你会找到答案和我必须做的改变。
您可以优化覆盖以更好地适应垫选择的大小。
结果
{{clickEvent}}
<div class="select-container">
<mat-form-field>
<mat-select #matSelect placeholder=" Normal behavior on single click" (openedChange)=" openedChange($event)">
<mat-option *ngFor="let option of options" [value]="option.value">
{{ option.viewValue }}
</mat-option>
</mat-select>
</mat-form-field>
<div class="click_listener-container" (click)="singleClick($event);">
</div>
</div>
enum values {
OPTION_1,
OPTION_2,
OPTION_3
}
@Component({
selector: 'select-overview-example',
templateUrl: 'select-overview-example.html',
styleUrls: ['select-overview-example.css']
})
export class SelectOverviewExample {
@ViewChild('matSelect') matSelect: MatSelect;
options = [
{ value: values.OPTION_1, viewValue: 'Option 1' },
{ value: values.OPTION_2, viewValue: 'Option 2' },
{ value: values.OPTION_3, viewValue: 'Option 3' }
];
disableMatSelect = true;
isSingleClick = false;
clickEvent = 'Not Clicked';
constructor() {}
async singleClick(event) {
event.stopPropagation();
if (this.isSingleClick) {
this.doubleClick();
} else {
this.isSingleClick = true;
setTimeout(() => {
if (this.isSingleClick && event.type == 'click') {
console.log('single click');
this.clickEvent = 'Single Click';
this.isSingleClick = false;
this.matSelect.open();
}
}, 250);
}
}
doubleClick() {
this.isSingleClick = false;
this.clickEvent = 'Double Click';
console.log('======>Doble click');
}
openedChange(opened: boolean) {
if (opened === false) {
this.disableMatSelect = true;
console.log('disableMatSelect==', this.disableMatSelect);
}
}
}
编辑
如果您有多个垫子选择,您可以使用@ViewChildren
如下
@ViewChildren('matSelect')
matSelections: QueryList<MatSelect>
然后,您可以像跟随一样循环遍历元素。
this.matSelections.toArray().map(async (matSelect) => {
console.log(matSelect)
}),
推荐阅读
- r-markdown - RMarkdown 到 PPT:未加载 reference_doc()
- c - 无法制作:函数“http_write_chunked”的隐式声明
- nestjs - Nestjs 服务器不为 socket.io 客户端提供服务
- mysql - mysql select查询不适用于通过用户变量设置的限制和偏移量
- mysql - mariadb vs mysql * 两者如何处理 SELECT * FROM Customers WHERE City LIKE '[acs]%';
- javascript - 从类 ajaxSuccess 事件侦听器方法指向类“this”的方法是什么?
- python - 无法理解此代码中的质心和距离公式
- angular - 如何更改登录组件以使其使用用户名而不是电子邮件?
- python - Python:如何同时创建数据库和 GUI?
- karate - 空手道:在两个不同的 url 上运行一个场景文件