当用户单击按钮时,addElement
方法会将对象推送到elements
数组,并创建新的输入字段。是否可以专注于新创建的元素?输入没有唯一的 ID。
模板:
<div *ngFor="let foo of elements">
<input class="input" value="{{ foo.value }}" />
</div>
<button (click)="addElement()"></button>
方法:
public addElement() {
this.elements.push({ value: 'new' });
}
我在这个应用程序中使用 Angular 9。
您需要通过ViewChildren
装饰器查询所有输入,然后每次调用addElement
时也会调用ngAfterViewChecked
。因此,您可以使用此钩子来聚焦上次已创建的输入。
<div *ngFor="let foo of elements">
<input
#input
class="input"
[value]="foo.value"
/>
</div>
<button (click)="addElement()"></button>
@ViewChildren('input') inputs: QueryList<ElementRef>;
addElement() {
this.elements.push({ value: 'new' });
}
ngAfterViewChecked() {
this.inputs.last.nativeElement.focus();
}
否则,您可以自己检查,不要依赖生命周期钩子,因为ngAfterViewChecked
中的此逻辑可能会影响应用程序中的 smth:
@ViewChildren('input') inputs: QueryList<ElementRef>;
constructor(private changeDetectorRef: ChangeDetectorRef) {
}
addElement() {
this.elements.push({ value: 'new' });
/* run change detection manually to create input element and have access to the last input */
this.changeDetectorRef.detectChanges();
this.inputs.last.nativeElement.focus();
}
<小时 />https://angular.io/api/core/ViewChildren#description
https://angular.io/guide/lifecycle-hooks#lifecycle-event-sequence
ngFor 中的角度元素可以使用ViewChildren
访问。
您可以通过以下方式更新addElement
函数以实现结果。
@ViewChildren("row") rows;
public addElement() {
this.elements.push({ value: "new" });
setTimeout(() => {
this.rows.last.nativeElement.focus();
}, 0);
}
并更新您的 ngFor 模板,如下所示:
<div *ngFor="let foo of elements">
<input #row class="input" value="{{ foo.value }}" />
</div>
这是堆栈闪电战的示例: https://stackblitz.com/edit/angular-ivy-xtkvaz
您可以通过跟踪div 子组件的任何更改来实现此目标。每次创建或刷新div
时,请将焦点放在最后一个input
子项上。
为此,您需要:
- 一个指令
div
向容器添加一些行为逻辑 - 一个指令来标识每个
input
标签
这样,您的模板可以是:
<div track-focus *ngFor="let foo of elements">
<input auto-focus ... />
</div>
<button (click)="addElement()">Add</button>
@Directive({
selector: 'input[auto-focus]',
})
export class InputAutoFocusDirective {}
@Directive({
selector: '[track-focus]',
})
export class TrackFocusDirective implements AfterContentInit {
@ContentChildren(InputAutofocusDirective, {
read: ElementRef,
})
children: QueryList<InputAutoFocusDirective>;
ngAfterContentInit() {
const input = (this.children.last as ElementRef)
.nativeElement as HTMLElement;
if (input) {
input.focus();
}
}
}
在这里,您有一个可重复使用的解决方案。