Я работаю с клиентским приложением с Angular 5, и мне нужно, чтобы поле поиска было скрыто, но при нажатии кнопки поле поиска должно отображаться и фокусироваться.
Я пробовал несколько способов найти в StackOverflow с помощью директивы или около того, но не смог.
Вот пример кода:
@Component({
selector: 'my-app',
template: `
<div>
<h2>Hello</h2>
</div>
<button (click) ="showSearch()">Show Search</button>
<p></p>
<form>
<div >
<input *ngIf="show" #search type="text" />
</div>
</form>
`,
})
export class App implements AfterViewInit {
@ViewChild('search') searchElement: ElementRef;
show: false;
name:string;
constructor() {
}
showSearch(){
this.show = !this.show;
this.searchElement.nativeElement.focus();
alert("focus");
}
ngAfterViewInit() {
this.firstNameElement.nativeElement.focus();
}
Поле поиска не настроено на фокус.
Как я могу это сделать?
setTimeout(() => { this.searchElement.nativeElement.focus() }, 100)
Для этого вам следует использовать html- автофокус :
Примечание: если ваш компонент сохраняется и используется повторно, он будет выполнять автофокусировку только при первом присоединении фрагмента. Это можно преодолеть, имея глобальный прослушиватель dom, который проверяет атрибут автофокуса внутри фрагмента dom, когда он прикреплен, а затем повторно применяет его или фокусируется через javascript.
источник
Эта директива мгновенно сфокусируется и выделит любой текст в элементе, как только он отобразится. В некоторых случаях для этого может потребоваться setTimeout, он мало тестировался.
И в HTML:
источник
Я собираюсь взвесить это (решение Angular 7)
import {AfterViewInit, Directive, ElementRef, Input,} from '@angular/core'; @Directive({ selector: 'input[appFocus]', }) export class FocusDirective implements AfterViewInit { @Input('appFocus') private focused: boolean = false; constructor(public element: ElementRef<HTMLElement>) { } ngAfterViewInit(): void { // ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. if (this.focused) { setTimeout(() => this.element.nativeElement.focus(), 0); } } }
источник
Это работает в Angular 8 без setTimeout:
Объяснение: Хорошо, это работает из-за: Обнаружения изменений. По той же причине работает setTimout, но при запуске setTimeout в Angular он обходит Zone.js и снова запускает все проверки, и это работает, потому что, когда setTimeout завершен, все изменения завершаются. С правильным крючком жизненного цикла (AfterContentChecked) можно достичь того же результата, но с тем преимуществом, что дополнительный цикл не будет выполняться. Функция срабатывает, когда все изменения проверены и переданы, и запускается после хуков AfterContentInit и DoCheck. Если я ошибаюсь, поправьте меня.
Больше одного жизненного цикла и обнаружение изменений на https://angular.io/guide/lifecycle-hooks
ОБНОВЛЕНИЕ : я нашел еще лучший способ сделать это, если использовать Angular Material CDK, a11y-package. Сначала импортируйте A11yModule в модуль, объявляющий компонент, в котором есть поле ввода. Затем используйте директивы cdkTrapFocus и cdkTrapFocusAutoCapture и используйте это в html и установите tabIndex на входе:
У нас возникли некоторые проблемы с нашими раскрывающимися списками, касающимися позиционирования и скорости реакции, и мы начали использовать OverlayModule из cdk, и этот метод с использованием A11yModule работает безупречно.
источник
cdkTrapFocusAutoCapture
атрибут, но я изменил ваш первый пример в свой код. По неизвестным для меня причинам он не работал с ловушкой жизненного цикла AfterContentChecked, а только с OnInit. В частности, с AfterContentChecked я не могу изменить фокус и перейти (с помощью мыши или клавиатуры) на другой ввод без этой директивы в той же форме.Чтобы выполнить выполнение после изменения логического значения и избежать использования тайм-аута, вы можете сделать:
источник
В Angular, в самом HTML, вы можете установить фокус на ввод при нажатии кнопки.
источник
mat-select
selectionChanged
событию, которое происходит раньше других элементов пользовательского интерфейса, поэтому перетягивание фокуса в этот момент не сработало. Вместо этого я должен был написать методsetFocus(el:HTMLElement):void { setTimeout(()=>el.focus(),0); }
и вызывать его из обработчика событий:<mat-select (selectionChanged)="setFocus(myInput)">
. Не так красиво, но просто и хорошо работает. Спасибо!Также есть атрибут DOM,
cdkFocusInitial
который у меня работает с входными данными. Подробнее об этом можно прочитать здесь: https://material.angular.io/cdk/a11y/overviewисточник
Только с использованием Angular Template
источник
html компонента:
<input [cdkTrapFocusAutoCapture]="show" [cdkTrapFocus]="show">
контроллер компонента:
showSearch() { this.show = !this.show; }
..и не забываем про импорт A11yModule из @ angular / cdk / a11y
import { A11yModule } from '@angular/cdk/a11y'
источник
Более простой способ - сделать это.
источник