专注于 ngFor 内部的输入
Focus on input inside ngFor
当用户单击按钮时,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
您可以通过跟踪 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();
}
}
}
在这里,您有一个可重复使用的解决方案。
Angular 可以使用 ViewChildren
.
访问 ngFor 中的元素
您可以通过以下方式更新您的 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>
这里是 stackblitz 的例子:https://stackblitz.com/edit/angular-ivy-xtkvaz
当用户单击按钮时,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
您可以通过跟踪 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();
}
}
}
在这里,您有一个可重复使用的解决方案。
Angular 可以使用 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>
这里是 stackblitz 的例子:https://stackblitz.com/edit/angular-ivy-xtkvaz