至於解決的重點問題,您可以創建一個屬性指令,focusMe
:
import {Component, Directive, ElementRef} from 'angular2/core';
@Directive({
selector: '[focusMe]'
})
export class FocusDirective {
constructor(private el: ElementRef) {}
ngAfterViewInit() {
this.el.nativeElement.focus();
}
}
@Component({
selector: 'my-app',
directives: [FocusDirective],
template: `<h1>My First Angular 2 App</h1>
<button (click)="toggle()">toggle</button>
<input focusMe *ngIf="isVisible">
`
})
export class AppComponent {
constructor() { console.clear(); }
private isVisible = false;
toggle() {
this.isVisible = !this.isVisible;
}
}
Plunker
更新1:添加用於再聚焦功能的解決方案:
import {Component, Directive, ElementRef, Input} from 'angular2/core';
@Directive({
selector: '[focusMe]'
})
export class FocusMe {
@Input('focusMe') hasFocus: boolean;
constructor(private elementRef: ElementRef) {}
ngAfterViewInit() {
this.elementRef.nativeElement.focus();
}
ngOnChanges(changes) {
//console.log(changes);
if(changes.hasFocus && changes.hasFocus.currentValue === true) {
this.elementRef.nativeElement.focus();
}
}
}
@Component({
selector: 'my-app',
template: `<h1>My First Angular 2 App</h1>
<button (click)="showInput()">Make it visible</button>
<input *ngIf="inputIsVisible" [focusMe]="inputHasFocus">
<button (click)="focusInput()" *ngIf="inputIsVisible">Focus it</button>
`,
directives:[FocusMe]
})
export class AppComponent {
private inputIsVisible = false;
private inputHasFocus = false;
constructor() { console.clear(); }
showInput() {
this.inputIsVisible = true;
}
focusInput() {
this.inputHasFocus = true;
setTimeout(() => this.inputHasFocus = false, 50);
}
}
Plunker
使用setTimeout()
到聚焦屬性重置爲false
是創建一個事件/輸出屬性的替代在FocusDirective上,以及emit()
時focus()
被調用的事件。然後,AppComponent將偵聽該事件並重置焦點屬性。
更新2:這是使用ViewChild添加重新聚焦功能的替代方法/更好的方法。我們不需要這樣跟蹤焦點狀態,也不需要FocusMe指令中的輸入屬性。
import {Component, Directive, ElementRef, Input, ViewChild} from 'angular2/core';
@Directive({
selector: '[focusMe]'
})
export class FocusMe {
constructor(private elementRef: ElementRef) {}
ngAfterViewInit() {
// set focus when element first appears
this.setFocus();
}
setFocus() {
this.elementRef.nativeElement.focus();
}
}
@Component({
selector: 'my-app',
template: `<h1>My First Angular 2 App</h1>
<button (click)="showInput()">Make it visible</button>
<input *ngIf="inputIsVisible" focusMe>
<button (click)="focusInput()" *ngIf="inputIsVisible">Focus it</button>
`,
directives:[FocusMe]
})
export class AppComponent {
@ViewChild(FocusMe) child;
private inputIsVisible = false;
constructor() { console.clear(); }
showInput() {
this.inputIsVisible = true;
}
focusInput() {
this.child.setFocus();
}
}
Plunker
更新3:這是又不需要一個指令,它仍然採用ViewChild另一種選擇,但我們通過本地模板變量訪問子而不是屬性指令(感謝@alexpods爲the tip):
import {Component, ViewChild, NgZone} from 'angular2/core';
@Component({
selector: 'my-app',
template: `<h1>Focus test</h1>
<button (click)="showInput()">Make it visible</button>
<input #input1 *ngIf="input1IsVisible">
<button (click)="focusInput1()" *ngIf="input1IsVisible">Focus it</button>
`,
})
export class AppComponent {
@ViewChild('input1') input1ElementRef;
private input1IsVisible = false;
constructor(private _ngZone: NgZone) { console.clear(); }
showInput() {
this.input1IsVisible = true;
// Give ngIf a chance to render the <input>.
// Then set the focus, but do this outside the Angualar zone to be efficient.
// There is no need to run change detection after setTimeout() runs,
// since we're only focusing an element.
this._ngZone.runOutsideAngular(() => {
setTimeout(() => this.focusInput1(), 0);
});
}
setFocus(elementRef) {
elementRef.nativeElement.focus();
}
ngDoCheck() {
// if you remove the ngZone stuff above, you'll see
// this log 3 times instead of 1 when you click the
// "Make it visible" button.
console.log('doCheck');
}
focusInput1() {
this.setFocus(this.input1ElementRef);
}
}
Plunker
更新4:我更新更新3代碼使用NgZone,這樣我們就不會引起角度的變化檢測算法對setTimeout()
結束後運行。 (關於更改檢測的更多信息,請參閱this answer)。
更新5:我更新了上述plunker中的代碼,以使用Renderer使其成爲web worker安全。不鼓勵在nativeElement
上直接訪問focus()
。
focusInput1() {
this._renderer.invokeElementMethod(
this.input1ElementRef.nativeElement, 'focus', []);
}
我從這個問題中學到了很多東西。
另請參見https://github.com/angular/angular/issues/6179 –
我已經填充了有關角度回購的問題,因爲如果我們考慮實際的文檔說明「我們可以引用本地模板變量相同的元素,同胞元素或其任何子元素。「。 –