Скрыть элемент на размытие ввода, кроме тех случаев, когда элемент нажат - PullRequest
1 голос
/ 28 сентября 2019

У меня есть следующий вариант использования:

Существует input, и всплывающее окно должно отображаться рядом со входом, когда он имеет фокус.Таким образом, в то время как у input есть фокус, пользователь может либо ввести input, либо использовать всплывающее окно для выбора чего-либо.

Когда пользователь закончит, он может расфокусировать элемент, либо щелкнув где-нибудь ещеили нажав клавишу Tab и сфокусировав следующий элемент.Однако, если он нажимает кнопку внутри всплывающего окна, всплывающее окно должно оставаться открытым, а ввод должен оставаться сфокусированным, чтобы пользователь мог продолжать печатать.

Проблема, с которой я столкнулся, заключается в том, что угловые процессы (размытие) наввод перед обработкой (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;
        }
    }
}

Я ожидаю следующего поведения:

  • Когда фокус ввода становится видимым, всплывающее окно видно
  • Когда пользователь щелкает снаружи где-либона странице, которая не является всплывающим или входным, всплывающее окно закрывается
  • Когда пользователь нажимает на вкладку, когда ввод находится в фокусе, ввод теряет фокус, а всплывающее окно закрывается
  • Когда пользователь щелкаеткнопка во всплывающем окне, этот номер выбран

Мне кажется, что я могу заставить работать только второй, третий или четвертый критерии (см. флажок в демонстрационной версии).

Что я уже пробовал:

  • Использование @HostListener с focusin, focusout или focus или (blur) = "someFunction (event), чтобы выяснить, какой элемент имеет новый фокус, чтобы проверить, находится ли этот элемент во всплывающем окне или на входе -> это, похоже, не работает, так как во время focusout-В случае, если еще не ясно, кто получит новый фокус
  • с использованием тайм-аута, чтобы Angular уже закончил обрабатывать событие щелчка по истечении тайм-аута -> это похоже на работу, но работа с тайм-аутами - действительно неуклюжее решение,может легко сломаться

У кого-нибудь есть решение?

1 Ответ

1 голос
/ 28 сентября 2019

Это больше похоже на Javascript.Событие blur происходит до события click.Событие click происходит только после отпускания кнопки мыши.

Здесь вы можете использовать событие mousedown в своих интересах.Событие mousedown происходит до события blur.Просто наберите preventDefault на mousedown в поповерных кнопках, чтобы input не потерял фокус.Это также решит проблему, когда ваш input мигает, когда вы нажимаете кнопки во всплывающем окне, чтобы вы могли избавиться от this.mainInput.nativeElement.focus(); в вашей функции selectNumber.

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

Вот рабочий пример StackBlitz .

...