当输入模糊时,隐藏弹出窗口,除非单击弹出窗口 [英] Hide popup when input is blurred except when popup is clicked

查看:79
本文介绍了当输入模糊时,隐藏弹出窗口,除非单击弹出窗口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下用例:

有一个 input ,只要有焦点,就应该在该输入旁边显示一个弹出窗口.因此,当 input 具有焦点时,用户可以输入 input 或使用弹出窗口选择内容.

There is an input and a popup should be displayed next to the input whenever it has focus. So while the input has focus, the user can either type into the input or use the popup to select something.

用户完成操作后,可以通过单击以下方式取消元素的焦点在其他位置或通过按Tab键并集中关注下一个元素.但是,如果他单击弹出窗口内的按钮,则该弹出窗口应保持不变打开,输入应保持焦点,以便用户可以继续打字.

When the user is done, he can unfocus the element either by clicking somewhere else or by pressing tab and focussing the next element. However, if he clicks a button inside the popup, the popup should stay open and the input should stay focused so that the user can continue typing.

我遇到的问题是,在对弹出窗口中的(单击)进行处理之前,对输入进行角处理(模糊).这意味着当用户在弹出窗口中单击,输入失去焦点,它被隐藏,然后用户的点击将不再被处理.

The problem that I have is that angular processes (blur) on the input before it processes (click) in the popup. That means that when the user clicks in the popup, the input loses focus, it gets hidden, and then the click of the user won't be processed anymore.

我针对该问题做了 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;
        }
    }
}

我期望以下行为:

  • 当输入获得焦点时,弹出窗口可见
  • 当用户在页面以外的任何地方单击时,弹出窗口或输入,弹出窗口关闭
  • 当用户在输入聚焦时按下选项卡时,输入失去焦点,弹出窗口关闭
  • 当用户单击弹出窗口中的按钮时,该数字已选定

我似乎只能获得第二,第三或第四名工作标准(请参见演示中的复选框).

I only seem to be able to get either the second and third or the fourth criteria to work (see the checkbox in the demo).

我已经尝试过的:

  • 将@HostListener与focusin,focusout或focus一起使用,或(模糊)="someFunction(事件)以找出哪个元素具有新的焦点.检查该元素是在弹出框中还是在输入->中这个似乎不起作用,因为在焦点事件发生时还没有明确谁获得了新的焦点
  • 使用超时,以便角度已经完成处理超时结束时的点击事件->这似乎工作,但工作超时是一个非常笨拙的解决方案,可能很容易破解

有人可以解决吗?

推荐答案

这更像是Java脚本. blur 事件发生在 click 事件之前. click 事件仅在释放鼠标按钮后发生.

This is more of a Javascript thing. The blur event takes place before the click event. The click event only takes place once the mouse button is released.

您可以在此处使用 mousedown 事件以发挥自己的优势. mousedown 事件在 blur 事件之前发生.只需在弹出按钮中的 mousedown 上调用 preventDefault ,即可防止 input 失去焦点.这也可以解决以下问题:当您单击弹出式窗口中的按钮时,您的 input 闪烁,因此您可以在 selectNumber 函数.

You can use the mousedown event here to your advantage. The mousedown event takes place before the blur event. Simply call preventDefault on mousedown in the popover buttons to prevent the input from losing focus. This would also solve the issue where your input blinks when you click buttons in the popover so you can get rid of this.mainInput.nativeElement.focus(); in your selectNumber function.

<button *ngFor="let number of numbers" (mousedown)="$event.preventDefault()" (click)="selectNumber(number.raw)">{{number.formatted}}</button>

这是 StackBlitz 上的有效示例.

这篇关于当输入模糊时,隐藏弹出窗口,除非单击弹出窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆