У меня есть следующий вариант использования:
Существует 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 уже закончил обрабатывать событие щелчка по истечении тайм-аута -> это похоже на работу, но работа с тайм-аутами - действительно неуклюжее решение,может легко сломаться
У кого-нибудь есть решение?