Saya sedang mengerjakan aplikasi front-end dengan Angular 5, dan saya perlu menyembunyikan kotak pencarian, tetapi dengan mengklik tombol, kotak pencarian harus ditampilkan dan difokuskan.
Saya telah mencoba beberapa cara yang ditemukan di StackOverflow dengan direktif atau lebih, tetapi tidak berhasil.
Berikut ini contoh kode:
@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();
}
Kotak pencarian tidak diatur ke fokus.
Bagaimana saya bisa melakukan itu?
setTimeout(() => { this.searchElement.nativeElement.focus() }, 100)
Anda harus menggunakan autofokus html untuk ini:
Catatan: jika komponen Anda dipertahankan dan digunakan kembali, itu hanya akan melakukan fokus otomatis saat pertama kali fragmen dipasang. Hal ini dapat diatasi dengan memiliki pendengar dom global yang memeriksa atribut fokus otomatis di dalam fragmen dom saat dilampirkan, lalu menerapkannya kembali atau memfokuskan melalui javascript.
sumber
Arahan ini akan langsung fokus dan memilih teks apa pun di elemen segera setelah ditampilkan. Ini mungkin memerlukan setTimeout untuk beberapa kasus, ini belum banyak diuji.
Dan di HTML:
sumber
Saya akan mempertimbangkan ini (Solusi Sudut 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); } } }
sumber
Ini berfungsi di Angular 8 tanpa setTimeout:
Penjelasan: Ok jadi ini berfungsi karena: Deteksi perubahan. Itu alasan yang sama bahwa setTimout berfungsi, tetapi saat menjalankan setTimeout di Angular, ia akan melewati Zone.js dan menjalankan semua pemeriksaan lagi, dan berfungsi karena saat setTimeout selesai semua perubahan selesai. Dengan hook siklus hidup yang benar (AfterContentChecked), hasil yang sama dapat dicapai, tetapi dengan keuntungan bahwa siklus tambahan tidak akan dijalankan. Fungsi ini akan aktif ketika semua perubahan diperiksa dan diteruskan, dan berjalan setelah hook AfterContentInit dan DoCheck. Jika saya salah di sini tolong perbaiki saya.
Lebih dari satu siklus proses dan deteksi perubahan di https://angular.io/guide/lifecycle-hooks
PEMBARUAN : Saya menemukan cara yang lebih baik untuk melakukan ini jika menggunakan Angular Material CDK, paket a11y. Pertama impor A11yModule di modul menyatakan komponen Anda memiliki masukan-lapangan di Kemudian gunakan. CdkTrapFocus dan cdkTrapFocusAutoCapture arahan dan penggunaan seperti ini di html dan set tabindex pada input:
Kami mengalami beberapa masalah dengan tarik-turun terkait pemosisian dan daya tanggap dan mulai menggunakan OverlayModule dari cdk, dan metode yang menggunakan A11yModule ini bekerja dengan sempurna.
sumber
cdkTrapFocusAutoCapture
atribut, tetapi saya mengubah contoh pertama Anda menjadi kode saya. Untuk alasan yang tidak diketahui (bagi saya) itu tidak bekerja dengan hook siklus hidup AfterContentChecked, tetapi hanya dengan OnInit. Dalam particolar dengan AfterContentChecked saya tidak dapat mengubah fokus dan memindahkan (dengan mouse atau papan tombol) ke input lain tanpa arahan dalam bentuk yang sama.Di Angular, di dalam HTML itu sendiri, Anda dapat mengatur fokus ke input dengan mengklik tombol.
sumber
mat-select
selectionChanged
acara yang terjadi sebelum hal-hal UI lainnya, jadi menarik fokus pada saat itu tidak berhasil. Sebaliknya saya harus menulis metodesetFocus(el:HTMLElement):void { setTimeout(()=>el.focus(),0); }
dan menyebutnya dari event handler:<mat-select (selectionChanged)="setFocus(myInput)">
. Tidak sebaik, tapi sederhana dan bekerja dengan baik. Terima kasih!Untuk melakukan eksekusi setelah boolean berubah dan menghindari penggunaan timeout yang bisa Anda lakukan:
sumber
Ada juga atribut DOM yang disebut
cdkFocusInitial
yang berfungsi untuk saya pada input. Anda dapat membaca lebih lanjut di sini: https://material.angular.io/cdk/a11y/overviewsumber
Hanya menggunakan Template Angular
sumber
html komponen:
<input [cdkTrapFocusAutoCapture]="show" [cdkTrapFocus]="show">
pengontrol komponen:
showSearch() { this.show = !this.show; }
..dan jangan lupa import A11yModule dari @ angular / cdk / a11y
import { A11yModule } from '@angular/cdk/a11y'
sumber
Saya mengalami skenario yang sama, ini berhasil untuk saya tetapi saya tidak memiliki fitur "sembunyikan / tampilkan" yang Anda miliki. Jadi mungkin Anda bisa terlebih dahulu memeriksa apakah Anda mendapatkan fokus ketika Anda memiliki bidang yang selalu terlihat, dan kemudian mencoba untuk memecahkan mengapa tidak berhasil saat Anda mengubah visibilitas (mungkin itu sebabnya Anda perlu menerapkan tidur atau janji)
Untuk mengatur fokus, ini adalah satu-satunya perubahan yang perlu Anda lakukan:
input mat Html Anda harus:
di kelas TS Anda, referensi seperti ini di bagian variabel (
Tombol Anda baik-baik saja, menelepon:
dan hanya itu. Anda dapat memeriksa solusi ini di posting ini yang saya temukan, jadi terima kasih kepada -> https://codeburst.io/focusing-on-form-elements-the-angular-way-e9a78725c04f
sumber
Cara yang lebih mudah juga dengan melakukan ini.
sumber