编辑行时如何聚焦到特定单元格
How to focus to a specific cell when editing a row
当 table 的第一列中有一个元素并且我编辑了一行时,焦点转到了错误的位置。
我正在使用 kendo 网格。我有一个 table,第一列中有一个按钮,只有在满足某些条件时才会显示。第二行是我要编辑的文本。第三行有一个编辑按钮。如果我按下编辑按钮并且第一列为空,焦点将转到第二列,其中包含已编辑的文本。如果第一列不为空,当我按下编辑按钮时,焦点转到第一个按钮,实际编辑的文本没有焦点。
我看到here有一个方法叫做focus
,但我不知道如何使用它,也没有找到任何例子。
我也看到了类似的问题 here 但它是针对 jQuery,而不是针对 Angular。
(非常简化的)代码如下:
<kendo-grid-column>
<!--Column 1: Button, depending on some condition-->
<ng-template kendoGridCellTemplate>
<button *ngIf="someCondition">HELLO</button>
</ng-template>
</kendo-grid-column>
<kendo-grid-column>
<!--Column 2: Editable -->
<ng-template kendoGridCellTemplate>
<span>whatever</span>
</ng-template>
<ng-template kendoGridEditTemplate>
<input [formControl]="formGroup.get('field')">
</ng-template>
</kendo-grid-column>
<kendo-grid-column>
<!--Column 3: Edit button-->
<ng-template kendoGridCellTemplate>
<button kendoGridEditCommand type="button">Edit</button>
</ng-template>
</kendo-grid-column>
我希望当我按下编辑按钮时,第二列始终处于焦点状态。非常感谢!
我借助这个 kendo demo 实现了您想要实现的目标,这表明您需要使用 settimeout 专注于您想要的输入。
import { Observable } from 'rxjs/Observable';
import { Component, OnInit, Inject } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { GridDataResult } from '@progress/kendo-angular-grid';
import { State, process } from '@progress/kendo-data-query';
import { Product } from './model';
import { EditService } from './edit.service';
import { map } from 'rxjs/operators/map';
@Component({
selector: 'my-app',
template: `
<kendo-grid
[data]="view | async"
[height]="533"
[pageSize]="gridState.take" [skip]="gridState.skip" [sort]="gridState.sort"
[pageable]="true" [sortable]="true"
(dataStateChange)="onStateChange($event)"
(edit)="editHandler($event)" (cancel)="cancelHandler($event)"
(save)="saveHandler($event)" (remove)="removeHandler($event)"
(add)="addHandler($event)"
[navigable]="true"
>
<ng-template kendoGridToolbarTemplate>
<button kendoGridAddCommand>Add new</button>
</ng-template>
<kendo-grid-column>
<ng-template kendoGridCellTemplate let-dataItem>
<button *ngIf="dataItem.UnitPrice%2==0" kendoGridFocusable >HELLO</button>
</ng-template>
</kendo-grid-column>
<kendo-grid-column field="ProductName" title="Product Name"></kendo-grid-column>
<kendo-grid-column field="UnitPrice" editor="numeric" title="Price"></kendo-grid-column>
<kendo-grid-column field="Discontinued" editor="boolean" title="Discontinued"></kendo-grid-column>
<kendo-grid-column field="UnitsInStock" editor="numeric" title="Units In Stock"></kendo-grid-column>
<kendo-grid-command-column title="command" width="220">
<ng-template kendoGridCellTemplate let-isNew="isNew">
<button kendoGridEditCommand [primary]="true">Edit</button>
<button kendoGridRemoveCommand>Remove</button>
<button kendoGridSaveCommand [disabled]="formGroup?.invalid">{{ isNew ? 'Add' : 'Update' }}</button>
<button kendoGridCancelCommand>{{ isNew ? 'Discard changes' : 'Cancel' }}</button>
</ng-template>
</kendo-grid-command-column>
</kendo-grid>
`
})
export class AppComponent implements OnInit {
public view: Observable<GridDataResult>;
public gridState: State = {
sort: [],
skip: 0,
take: 10
};
public formGroup: FormGroup;
private editService: EditService;
private editedRowIndex: number;
constructor(@Inject(EditService) editServiceFactory: any) {
this.editService = editServiceFactory();
}
public ngOnInit(): void {
this.view = this.editService.pipe(map(data => process(data, this.gridState)));
this.editService.read();
}
public onStateChange(state: State) {
this.gridState = state;
this.editService.read();
}
public addHandler({sender}) {
this.closeEditor(sender);
this.formGroup = new FormGroup({
'ProductID': new FormControl(),
'ProductName': new FormControl('', Validators.required),
'UnitPrice': new FormControl(0),
'UnitsInStock': new FormControl('', Validators.compose([Validators.required, Validators.pattern('^[0-9]{1,3}')])),
'Discontinued': new FormControl(false)
});
sender.addRow(this.formGroup);
}
public editHandler({sender, rowIndex, dataItem}) {
this.closeEditor(sender);
this.formGroup = new FormGroup({
'ProductID': new FormControl(dataItem.ProductID),
'ProductName': new FormControl(dataItem.ProductName, Validators.required),
'UnitPrice': new FormControl(dataItem.UnitPrice),
'UnitsInStock': new FormControl(
dataItem.UnitsInStock,
Validators.compose([Validators.required, Validators.pattern('^[0-9]{1,3}')])),
'Discontinued': new FormControl(dataItem.Discontinued)
});
this.editedRowIndex = rowIndex;
sender.editRow(rowIndex, this.formGroup);
setTimeout(() => {
(<HTMLElement>document.querySelector(`.k-grid-edit-row > td:nth-child() input`))
.focus();
});
}
public cancelHandler({sender, rowIndex}) {
this.closeEditor(sender, rowIndex);
}
public saveHandler({sender, rowIndex, formGroup, isNew}) {
const product: Product = formGroup.value;
this.editService.save(product, isNew);
sender.closeRow(rowIndex);
}
public removeHandler({dataItem}) {
this.editService.remove(dataItem);
}
private closeEditor(grid, rowIndex = this.editedRowIndex) {
grid.closeRow(rowIndex);
this.editedRowIndex = undefined;
this.formGroup = undefined;
}
}
此外,还请阅读 focusable directive
当 table 的第一列中有一个元素并且我编辑了一行时,焦点转到了错误的位置。
我正在使用 kendo 网格。我有一个 table,第一列中有一个按钮,只有在满足某些条件时才会显示。第二行是我要编辑的文本。第三行有一个编辑按钮。如果我按下编辑按钮并且第一列为空,焦点将转到第二列,其中包含已编辑的文本。如果第一列不为空,当我按下编辑按钮时,焦点转到第一个按钮,实际编辑的文本没有焦点。
我看到here有一个方法叫做focus
,但我不知道如何使用它,也没有找到任何例子。
我也看到了类似的问题 here 但它是针对 jQuery,而不是针对 Angular。
(非常简化的)代码如下:
<kendo-grid-column>
<!--Column 1: Button, depending on some condition-->
<ng-template kendoGridCellTemplate>
<button *ngIf="someCondition">HELLO</button>
</ng-template>
</kendo-grid-column>
<kendo-grid-column>
<!--Column 2: Editable -->
<ng-template kendoGridCellTemplate>
<span>whatever</span>
</ng-template>
<ng-template kendoGridEditTemplate>
<input [formControl]="formGroup.get('field')">
</ng-template>
</kendo-grid-column>
<kendo-grid-column>
<!--Column 3: Edit button-->
<ng-template kendoGridCellTemplate>
<button kendoGridEditCommand type="button">Edit</button>
</ng-template>
</kendo-grid-column>
我希望当我按下编辑按钮时,第二列始终处于焦点状态。非常感谢!
我借助这个 kendo demo 实现了您想要实现的目标,这表明您需要使用 settimeout 专注于您想要的输入。
import { Observable } from 'rxjs/Observable';
import { Component, OnInit, Inject } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { GridDataResult } from '@progress/kendo-angular-grid';
import { State, process } from '@progress/kendo-data-query';
import { Product } from './model';
import { EditService } from './edit.service';
import { map } from 'rxjs/operators/map';
@Component({
selector: 'my-app',
template: `
<kendo-grid
[data]="view | async"
[height]="533"
[pageSize]="gridState.take" [skip]="gridState.skip" [sort]="gridState.sort"
[pageable]="true" [sortable]="true"
(dataStateChange)="onStateChange($event)"
(edit)="editHandler($event)" (cancel)="cancelHandler($event)"
(save)="saveHandler($event)" (remove)="removeHandler($event)"
(add)="addHandler($event)"
[navigable]="true"
>
<ng-template kendoGridToolbarTemplate>
<button kendoGridAddCommand>Add new</button>
</ng-template>
<kendo-grid-column>
<ng-template kendoGridCellTemplate let-dataItem>
<button *ngIf="dataItem.UnitPrice%2==0" kendoGridFocusable >HELLO</button>
</ng-template>
</kendo-grid-column>
<kendo-grid-column field="ProductName" title="Product Name"></kendo-grid-column>
<kendo-grid-column field="UnitPrice" editor="numeric" title="Price"></kendo-grid-column>
<kendo-grid-column field="Discontinued" editor="boolean" title="Discontinued"></kendo-grid-column>
<kendo-grid-column field="UnitsInStock" editor="numeric" title="Units In Stock"></kendo-grid-column>
<kendo-grid-command-column title="command" width="220">
<ng-template kendoGridCellTemplate let-isNew="isNew">
<button kendoGridEditCommand [primary]="true">Edit</button>
<button kendoGridRemoveCommand>Remove</button>
<button kendoGridSaveCommand [disabled]="formGroup?.invalid">{{ isNew ? 'Add' : 'Update' }}</button>
<button kendoGridCancelCommand>{{ isNew ? 'Discard changes' : 'Cancel' }}</button>
</ng-template>
</kendo-grid-command-column>
</kendo-grid>
`
})
export class AppComponent implements OnInit {
public view: Observable<GridDataResult>;
public gridState: State = {
sort: [],
skip: 0,
take: 10
};
public formGroup: FormGroup;
private editService: EditService;
private editedRowIndex: number;
constructor(@Inject(EditService) editServiceFactory: any) {
this.editService = editServiceFactory();
}
public ngOnInit(): void {
this.view = this.editService.pipe(map(data => process(data, this.gridState)));
this.editService.read();
}
public onStateChange(state: State) {
this.gridState = state;
this.editService.read();
}
public addHandler({sender}) {
this.closeEditor(sender);
this.formGroup = new FormGroup({
'ProductID': new FormControl(),
'ProductName': new FormControl('', Validators.required),
'UnitPrice': new FormControl(0),
'UnitsInStock': new FormControl('', Validators.compose([Validators.required, Validators.pattern('^[0-9]{1,3}')])),
'Discontinued': new FormControl(false)
});
sender.addRow(this.formGroup);
}
public editHandler({sender, rowIndex, dataItem}) {
this.closeEditor(sender);
this.formGroup = new FormGroup({
'ProductID': new FormControl(dataItem.ProductID),
'ProductName': new FormControl(dataItem.ProductName, Validators.required),
'UnitPrice': new FormControl(dataItem.UnitPrice),
'UnitsInStock': new FormControl(
dataItem.UnitsInStock,
Validators.compose([Validators.required, Validators.pattern('^[0-9]{1,3}')])),
'Discontinued': new FormControl(dataItem.Discontinued)
});
this.editedRowIndex = rowIndex;
sender.editRow(rowIndex, this.formGroup);
setTimeout(() => {
(<HTMLElement>document.querySelector(`.k-grid-edit-row > td:nth-child() input`))
.focus();
});
}
public cancelHandler({sender, rowIndex}) {
this.closeEditor(sender, rowIndex);
}
public saveHandler({sender, rowIndex, formGroup, isNew}) {
const product: Product = formGroup.value;
this.editService.save(product, isNew);
sender.closeRow(rowIndex);
}
public removeHandler({dataItem}) {
this.editService.remove(dataItem);
}
private closeEditor(grid, rowIndex = this.editedRowIndex) {
grid.closeRow(rowIndex);
this.editedRowIndex = undefined;
this.formGroup = undefined;
}
}
此外,还请阅读 focusable directive