输入模糊时隐藏弹出窗口,单击弹出窗口时除外
Hide popup when input is blurred except when popup is clicked
我有以下用例:
有一个 input
,只要输入框有焦点,就会在输入框旁边显示一个弹出窗口。因此,当 input
具有焦点时,用户可以输入 input
或使用弹出窗口 select 某些内容。
当用户完成后,他可以通过单击取消对元素的聚焦
在其他地方或通过按 Tab 键并聚焦下一个元素。
但是,如果他单击弹出窗口中的按钮,弹出窗口应该保留
打开并且输入应该保持焦点,以便用户可以继续
打字。
我遇到的问题是 angular 在处理弹出窗口中的 (click)
之前处理(模糊)输入。这意味着当用户
在弹出窗口中单击,输入失去焦点,它被隐藏,然后
不再处理用户的点击。
我已经针对问题做了stackblitz-demo:
这是源代码:
app.component.html
<h1>Hello</h1>
<p>
Type 'one', 'two' or 'three' to change number or select a number
from popup.
<br>
<input type="checkbox" [(ngModel)]="hideHelperOnBlur" /> Hide
helper on blur (if this is set, then the buttons in the popup don't work
but if this is not set, the popup doesn't close if the input looses
focus -> how can I get both? The buttons to work but the popup still
closing on blur?)
</p>
Your number: {{selectedNumber}}
<p>
Change number:
<input [ngModel]="formattedNumber" (ngModelChange)="newNumberTyped($event)" (focus)="helperVisible = true"
(blur)="processBlur()" #mainInput />
<div *ngIf="helperVisible">
<button *ngFor="let number of numbers" (click)="selectNumber(number.raw)">{{number.formatted}} </button>
</div>
app.component.ts
import { Component, ViewChild, ElementRef } from '@angular/core';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
name = 'Angular';
formattedNumber: string = 'three';
selectedNumber: number = 3;
helperVisible: boolean = false;
numbers: any[] = [
{ raw: 1, formatted: 'one' },
{ raw: 2, formatted: 'two' },
{ raw: 3, formatted: 'three' }
];
@ViewChild('mainInput', { static: false })
mainInput: ElementRef;
hideHelperOnBlur: boolean;
newNumberTyped(newFormattedNumber: string) {
this.numbers.forEach((number) => {
if (newFormattedNumber == number.formatted) {
this.formattedNumber = newFormattedNumber;
this.selectedNumber = number.raw;
}
});
}
selectNumber(newRawNumber: number) {
this.numbers.forEach((number) => {
if (newRawNumber == number.raw) {
this.formattedNumber = number.formatted;
this.selectedNumber = newRawNumber;
}
});
this.mainInput.nativeElement.focus();
}
processBlur() {
if (this.hideHelperOnBlur) {
this.helperVisible = false;
}
}
}
我希望出现以下行为:
- 当输入获得焦点时,弹出窗口可见
- 当用户点击页面以外的任何地方时
弹窗或输入,弹窗关闭
- 当用户在输入聚焦时按下选项卡时,输入
失去焦点并且弹出窗口关闭
- 当用户单击弹出窗口中的按钮时,该数字是 selected
我好像只能拿到第二个第三个或者第四个
工作标准(参见演示中的复选框)。
我已经尝试过的:
- 将@HostListener 与 focusin、focusout 或 focus 一起使用或
(blur)="someFunction(event) 找出哪个元素有新的焦点
检查该元素是否在弹出窗口或输入中 -> this
似乎不起作用,因为在 focusout-event 时它还没有
明确谁获得了新焦点
- 使用超时,以便 angular 已经完成处理
超时结束时单击事件 - >这似乎有效但有效
超时是一个非常笨重的解决方案,可能很容易崩溃
有人有解决办法吗?
这更像是 Javascript 的事情。 blur
事件发生在 click
事件之前。 click
事件仅在释放鼠标按钮后发生。
您可以在这里利用 mousedown
活动。 mousedown
事件发生在 blur
事件之前。只需在弹出按钮中的 mousedown
上调用 preventDefault
即可防止 input
失去焦点。这也可以解决当您单击弹出窗口中的按钮时 input
闪烁的问题,这样您就可以在 selectNumber
函数中删除 this.mainInput.nativeElement.focus();
。
<button *ngFor="let number of numbers" (mousedown)="$event.preventDefault()" (click)="selectNumber(number.raw)">{{number.formatted}}</button>
这是 StackBlitz 上的一个工作示例。
我有以下用例:
有一个 input
,只要输入框有焦点,就会在输入框旁边显示一个弹出窗口。因此,当 input
具有焦点时,用户可以输入 input
或使用弹出窗口 select 某些内容。
当用户完成后,他可以通过单击取消对元素的聚焦 在其他地方或通过按 Tab 键并聚焦下一个元素。 但是,如果他单击弹出窗口中的按钮,弹出窗口应该保留 打开并且输入应该保持焦点,以便用户可以继续 打字。
我遇到的问题是 angular 在处理弹出窗口中的 (click)
之前处理(模糊)输入。这意味着当用户
在弹出窗口中单击,输入失去焦点,它被隐藏,然后
不再处理用户的点击。
我已经针对问题做了stackblitz-demo:
这是源代码:
app.component.html
<h1>Hello</h1>
<p>
Type 'one', 'two' or 'three' to change number or select a number
from popup.
<br>
<input type="checkbox" [(ngModel)]="hideHelperOnBlur" /> Hide
helper on blur (if this is set, then the buttons in the popup don't work
but if this is not set, the popup doesn't close if the input looses
focus -> how can I get both? The buttons to work but the popup still
closing on blur?)
</p>
Your number: {{selectedNumber}}
<p>
Change number:
<input [ngModel]="formattedNumber" (ngModelChange)="newNumberTyped($event)" (focus)="helperVisible = true"
(blur)="processBlur()" #mainInput />
<div *ngIf="helperVisible">
<button *ngFor="let number of numbers" (click)="selectNumber(number.raw)">{{number.formatted}} </button>
</div>
app.component.ts
import { Component, ViewChild, ElementRef } from '@angular/core';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
name = 'Angular';
formattedNumber: string = 'three';
selectedNumber: number = 3;
helperVisible: boolean = false;
numbers: any[] = [
{ raw: 1, formatted: 'one' },
{ raw: 2, formatted: 'two' },
{ raw: 3, formatted: 'three' }
];
@ViewChild('mainInput', { static: false })
mainInput: ElementRef;
hideHelperOnBlur: boolean;
newNumberTyped(newFormattedNumber: string) {
this.numbers.forEach((number) => {
if (newFormattedNumber == number.formatted) {
this.formattedNumber = newFormattedNumber;
this.selectedNumber = number.raw;
}
});
}
selectNumber(newRawNumber: number) {
this.numbers.forEach((number) => {
if (newRawNumber == number.raw) {
this.formattedNumber = number.formatted;
this.selectedNumber = newRawNumber;
}
});
this.mainInput.nativeElement.focus();
}
processBlur() {
if (this.hideHelperOnBlur) {
this.helperVisible = false;
}
}
}
我希望出现以下行为:
- 当输入获得焦点时,弹出窗口可见
- 当用户点击页面以外的任何地方时 弹窗或输入,弹窗关闭
- 当用户在输入聚焦时按下选项卡时,输入 失去焦点并且弹出窗口关闭
- 当用户单击弹出窗口中的按钮时,该数字是 selected
我好像只能拿到第二个第三个或者第四个 工作标准(参见演示中的复选框)。
我已经尝试过的:
- 将@HostListener 与 focusin、focusout 或 focus 一起使用或 (blur)="someFunction(event) 找出哪个元素有新的焦点 检查该元素是否在弹出窗口或输入中 -> this 似乎不起作用,因为在 focusout-event 时它还没有 明确谁获得了新焦点
- 使用超时,以便 angular 已经完成处理 超时结束时单击事件 - >这似乎有效但有效 超时是一个非常笨重的解决方案,可能很容易崩溃
有人有解决办法吗?
这更像是 Javascript 的事情。 blur
事件发生在 click
事件之前。 click
事件仅在释放鼠标按钮后发生。
您可以在这里利用 mousedown
活动。 mousedown
事件发生在 blur
事件之前。只需在弹出按钮中的 mousedown
上调用 preventDefault
即可防止 input
失去焦点。这也可以解决当您单击弹出窗口中的按钮时 input
闪烁的问题,这样您就可以在 selectNumber
函数中删除 this.mainInput.nativeElement.focus();
。
<button *ngFor="let number of numbers" (mousedown)="$event.preventDefault()" (click)="selectNumber(number.raw)">{{number.formatted}}</button>
这是 StackBlitz 上的一个工作示例。