在输入模糊时隐藏元素(单击元素时除外) [英] Hide element on blur of input except when element is clicked

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

问题描述

我有以下用例:

有一个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 in to 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.

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

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

我期望以下行为:

  • 当输入获得焦点时,弹出窗口可见
  • 当用户在页面以外的任何地方单击时, 弹出窗口或输入,弹出窗口关闭
  • 当用户在输入聚焦时按Tab键时,输入 失去焦点,弹出窗口关闭
  • 当用户单击弹出窗口中的按钮时,将选择该数字
  • When the input gets focus the popup is visible
  • When the user clicks outside anywhere on the page that is not the popup or the input, the popup closes
  • When the user presses tab while the input is focussed, the input loses focus and the popup closes
  • When the user clicks a button in the popup, that number is selected

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

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一起使用,或 (blur)="someFunction(event)找出哪个元素具有新焦点 检查该元素是在弹出框中还是在输入中->此 似乎不起作用,因为在焦点事件发生时还没有 明确谁获得了新的焦点
  • 使用超时,以便角度已经完成处理 超时结束时的click事件->这似乎有效,但有效 超时是一个非常笨拙的解决方案,可能很容易破解
  • Using @HostListener with focusin, focusout or focus or (blur)="someFunction(event) to find out which element has the new focus to check whether that element is in the popup or the input -> this doesn't seem to work since at the time of focusout-event it is not yet clear who gets the new focus
  • using a timeout so that angular already finished processing the click event when the timeout is over -> this seems to work but working with timeouts is a really clunky solution that may break easily

有人可以解决吗?

推荐答案

这更像是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函数中的this.mainInput.nativeElement.focus();.

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天全站免登陆