Ich arbeite an einer Front-End-Anwendung mit Angular 5 und muss ein Suchfeld ausblenden, aber auf Knopfdruck sollte das Suchfeld angezeigt und fokussiert werden.
Ich habe einige Möglichkeiten ausprobiert, die in StackOverflow mit Direktive oder so gefunden wurden, kann aber keinen Erfolg haben.
Hier ist der Beispielcode:
@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();
}
Das Suchfeld ist nicht auf Fokus eingestellt.
Wie kann ich das machen?
setTimeout(() => { this.searchElement.nativeElement.focus() }, 100)
Sie sollten dafür den HTML- Autofokus verwenden :
Hinweis: Wenn Ihre Komponente beibehalten und wiederverwendet wird, wird der Autofokus nur beim ersten Anhängen des Fragments automatisch aktiviert. Dies kann überwunden werden, indem ein globaler Dom-Listener über ein Autofokus-Attribut in einem Dom-Fragment verfügt, wenn es angehängt ist, und es dann erneut anwendet oder über Javascript fokussiert.
quelle
Diese Anweisung fokussiert und wählt sofort jeden Text im Element aus, sobald er angezeigt wird. Dies kann in einigen Fällen ein setTimeout erfordern, es wurde nicht viel getestet.
Und im HTML:
quelle
Ich werde das abwägen (Angular 7 Solution)
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); } } }
quelle
Dies funktioniert in Angular 8 ohne setTimeout:
Erläuterung: Ok, das funktioniert aus folgenden Gründen: Änderungserkennung. Es ist der gleiche Grund, warum setTimout funktioniert, aber wenn ein setTimeout in Angular ausgeführt wird, umgeht es Zone.js und führt alle Überprüfungen erneut aus. Wenn das setTimeout abgeschlossen ist, werden alle Änderungen abgeschlossen. Mit dem richtigen Lifecycle Hook (AfterContentChecked) kann das gleiche Ergebnis erzielt werden, jedoch mit dem Vorteil, dass der zusätzliche Zyklus nicht ausgeführt wird. Die Funktion wird ausgelöst, wenn alle Änderungen überprüft und übergeben wurden, und wird nach den Hooks AfterContentInit und DoCheck ausgeführt. Wenn ich mich hier irre, korrigiere mich bitte.
Weitere Lebenszyklen und Änderungserkennung unter https://angular.io/guide/lifecycle-hooks
UPDATE : Ich habe einen noch besseren Weg gefunden, dies zu tun, wenn man Angular Material CDK verwendet, das a11y-Paket. Importieren Sie zuerst A11yModule in das Modul und deklarieren Sie die Komponente, in der Sie das Eingabefeld haben. Verwenden Sie dann die Direktiven cdkTrapFocus und cdkTrapFocusAutoCapture und verwenden Sie diese in HTML und setzen Sie tabIndex für die Eingabe:
Wir hatten einige Probleme mit unseren Dropdowns in Bezug auf Positionierung und Reaktionsfähigkeit und haben stattdessen begonnen, das OverlayModule aus dem CDK zu verwenden. Diese Methode mit A11yModule funktioniert einwandfrei.
quelle
cdkTrapFocusAutoCapture
Attribut, aber ich habe Ihr erstes Beispiel in meinen Code geändert. Aus unbekannten Gründen (für mich) funktionierte es nicht mit AfterContentChecked Lifecycle Hook, sondern nur mit OnInit. Insbesondere mit AfterContentChecked kann ich den Fokus nicht ändern und (mit Maus oder Tastatur) ohne diese Anweisung in derselben Form auf einen anderen Eingang wechseln.So führen Sie die Ausführung durch, nachdem sich der Boolesche Wert geändert hat, und vermeiden die Verwendung von Timeout:
quelle
In Angular können Sie in HTML selbst den Fokus so einstellen, dass er beim Klicken auf eine Schaltfläche eingegeben wird.
quelle
mat-select
selectionChanged
Ereignis, das vor anderen UI-Dingen auftritt, sodass das Ziehen des Fokus an diesem Punkt nicht funktioniert hat. Stattdessen musste ich eine Methode schreibensetFocus(el:HTMLElement):void { setTimeout(()=>el.focus(),0); }
und sie vom Event-Handler aufrufen :<mat-select (selectionChanged)="setFocus(myInput)">
. Nicht so schön, aber einfach und funktioniert gut. Danke!Es gibt auch ein DOM-Attribut,
cdkFocusInitial
das bei Eingaben für mich funktioniert. Weitere Informationen finden Sie hier: https://material.angular.io/cdk/a11y/overviewquelle
Nur Angular Template verwenden
quelle
HTML der Komponente:
<input [cdkTrapFocusAutoCapture]="show" [cdkTrapFocus]="show">
Controller der Komponente:
showSearch() { this.show = !this.show; }
..und vergessen Sie nicht, A11yModule aus @ angle / cdk / a11y zu importieren
import { A11yModule } from '@angular/cdk/a11y'
quelle
Einfacher ist es auch, dies zu tun.
quelle