输入模糊时隐藏弹出窗口,单击弹出窗口时除外

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;
        }
    }
}

我希望出现以下行为:

我好像只能拿到第二个第三个或者第四个 工作标准(参见演示中的复选框)。

我已经尝试过的:

有人有解决办法吗?

这更像是 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 上的一个工作示例。