在 Angular 2 \ 4 table 中上下键
Key up down in Angular 2 \ 4 table
如何在 Angular 中的 table 个单元格中编写按键向上和向下的功能? (就像我们如何使用向上和向下箭头键在 excel sheet 中的单元格中移动键一样)。
这是我的代码:
http://plnkr.co/edit/vk937A1VWNPIFQYkoPsM?p=preview
<table>
<thead>
<tr>
<th class="under-below" *ngFor="let col of columns">{{col.display}}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let row of rows">
<td *ngFor="let col of columns">
<div *ngIf="!col.editable">{{colLabelFunction(row, col)}}</div>
<input type="text" value="{{colLabelFunction(row, col)}}" *ngIf="col.editable">
</td>
</tr>
</tbody>
</table>
我想使用 keyup 和 keydown 键在 'Column 2' 文本输入(单元格)上上下移动。
我刚刚注意到我比您想要的更进一步并添加了 right/left 功能。如果你愿意,你可以把它们剪掉。
为此,您需要完成几件事:
- 绑定到按键事件和运行它们的函数
- 跟踪您的索引并将它们传递到函数中
- 获取对元素的引用并对它们调用焦点方法
- 把它们放在一起
项目 1:绑定到按键事件和 运行ning 功能
Angular 提供像这样易于使用的事件绑定:
<input #inputs type="text" value="{{colLabelFunction(row, col)}}" [class.hidden]="!col.editable"
(keyup.arrowdown)="shiftFocusDown(rowIdx, colIdx)"
(keyup.arrowup)="shiftFocusUp(rowIdx, colIdx)"
(keyup.arrowright)="shiftFocusRight(rowIdx, colIdx)"
(keyup.arrowleft)="shiftFocusLeft(rowIdx, colIdx)">
keyup 事件是通用的,然后 arrowdown 等是由 angular 提供的 shorthand。然后你只需设置你想用任何参数触发的功能。
项目 2 跟踪您的索引并传递给函数
你可以在上面看到我在这些事件上调用函数并传递 rowIdx 和 colIdx,以获取这些变量,你在 ngFor 中声明它们,例如:
<tr *ngFor="let row of rows; let rowIdx = index">
<td *ngFor="let col of columns; let colIdx = index">
index 是 ngFor 中提供的一个特殊变量,它给出了当前项目的索引。他们还公开了其他一些你可以声明和使用的东西,比如 first 和 last。
项目 3:获取元素引用
为此,我们必须做几件事,您可能已经在上面注意到,我没有在输入上使用 ngIf,而是设置了 class.disabled,然后我将 CSS 添加到隐藏组件声明中隐藏 class 的元素,例如:
styles: [`.hidden { display: none; }`]
我这样做是为了元素引用永远不会改变,原因稍后会很明显,我做的另一件事是将#inputs 添加到每个输入项,这是一个模板引用,我可以在组件代码中访问它:
@ViewChildren('inputs') inputs;
View children 可以接受几种不同类型的参数,在本例中它接受一个字符串,它将在模板中搜索与该字符串匹配的任何模板引用,并 return 它们在查询列表中。
项目 4:组合起来
我现在有适当的函数可以在所需的键事件上执行,带有所需的参数,以及我所有输入元素引用的平面列表。
现在我只需要编写代码来完成这项工作:
focusInput(rowIdx: number, colIdx: number) {
console.log(rowIdx, colIdx);
// convert ViewChildren querylist to an array to access by index
let inputEls = this.inputs.toArray();
// get the flat index from row/cols
let flatIdx = (rowIdx * this.columns.length) + colIdx;
// get that reference from the input array and use the native element focus() method
inputEls[flatIdx].nativeElement.focus();
}
shiftFocusDown(rowIdx:number, colIdx:number) {
console.log("DOWN", colIdx, rowIdx)
// add 1 but don't go beyond my row range
rowIdx = Math.min(rowIdx + 1, this.rows.length - 1);
this.focusInput(rowIdx, colIdx);
}
shiftFocusUp(rowIdx:number, colIdx:number) {
console.log("UP", colIdx, rowIdx);
// up 1, but not less than 0
rowIdx = Math.max(0, rowIdx - 1);
this.focusInput(rowIdx, colIdx);
}
shiftFocusLeft(rowIdx:number, colIdx:number) {
console.log("LEFT", rowIdx, colIdx);
// left one column, and correct for non editable columns to left
colIdx = colIdx - 1 - this.columns.slice(0, colIdx).reverse().findIndex(c => c.editable);
// don't need edge check bc findIndex returns -1 if none found or no items, so that corrects us back to start col automatically
this.focusInput(rowIdx, colIdx);
}
shiftFocusRight(rowIdx:number, colIdx:number) {
console.log("RIGHT", rowIdx, colIdx);
// right one column, and correct for non editable columns to right
colIdx = colIdx + 1 + this.columns.slice(colIdx + 1).findIndex(c => c.editable);
// don't need edge check bc findIndex returns -1 if none found or out of range, so that corrects us back to start col automatically
this.focusInput(rowIdx, colIdx);
}
这里的代码主要是找到下一个合适的 col/row 索引,然后将 x,y 转换成平面索引,这样我就可以在我的 viewchildren 列表中找到正确的引用并调用 focus()在上面。我需要所有元素引用始终存在的原因是,否则将很难从 x、y 中找出正确的平面索引。如果您真的需要它们不在那里,那么您可以修改此逻辑以使其工作。一点也不不可能。您也可以修改它以允许 "wrapping" 非常容易地围绕行。
如何在 Angular 中的 table 个单元格中编写按键向上和向下的功能? (就像我们如何使用向上和向下箭头键在 excel sheet 中的单元格中移动键一样)。
这是我的代码: http://plnkr.co/edit/vk937A1VWNPIFQYkoPsM?p=preview
<table>
<thead>
<tr>
<th class="under-below" *ngFor="let col of columns">{{col.display}}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let row of rows">
<td *ngFor="let col of columns">
<div *ngIf="!col.editable">{{colLabelFunction(row, col)}}</div>
<input type="text" value="{{colLabelFunction(row, col)}}" *ngIf="col.editable">
</td>
</tr>
</tbody>
</table>
我想使用 keyup 和 keydown 键在 'Column 2' 文本输入(单元格)上上下移动。
我刚刚注意到我比您想要的更进一步并添加了 right/left 功能。如果你愿意,你可以把它们剪掉。
为此,您需要完成几件事:
- 绑定到按键事件和运行它们的函数
- 跟踪您的索引并将它们传递到函数中
- 获取对元素的引用并对它们调用焦点方法
- 把它们放在一起
项目 1:绑定到按键事件和 运行ning 功能
Angular 提供像这样易于使用的事件绑定:
<input #inputs type="text" value="{{colLabelFunction(row, col)}}" [class.hidden]="!col.editable"
(keyup.arrowdown)="shiftFocusDown(rowIdx, colIdx)"
(keyup.arrowup)="shiftFocusUp(rowIdx, colIdx)"
(keyup.arrowright)="shiftFocusRight(rowIdx, colIdx)"
(keyup.arrowleft)="shiftFocusLeft(rowIdx, colIdx)">
keyup 事件是通用的,然后 arrowdown 等是由 angular 提供的 shorthand。然后你只需设置你想用任何参数触发的功能。
项目 2 跟踪您的索引并传递给函数
你可以在上面看到我在这些事件上调用函数并传递 rowIdx 和 colIdx,以获取这些变量,你在 ngFor 中声明它们,例如:
<tr *ngFor="let row of rows; let rowIdx = index">
<td *ngFor="let col of columns; let colIdx = index">
index 是 ngFor 中提供的一个特殊变量,它给出了当前项目的索引。他们还公开了其他一些你可以声明和使用的东西,比如 first 和 last。
项目 3:获取元素引用
为此,我们必须做几件事,您可能已经在上面注意到,我没有在输入上使用 ngIf,而是设置了 class.disabled,然后我将 CSS 添加到隐藏组件声明中隐藏 class 的元素,例如:
styles: [`.hidden { display: none; }`]
我这样做是为了元素引用永远不会改变,原因稍后会很明显,我做的另一件事是将#inputs 添加到每个输入项,这是一个模板引用,我可以在组件代码中访问它:
@ViewChildren('inputs') inputs;
View children 可以接受几种不同类型的参数,在本例中它接受一个字符串,它将在模板中搜索与该字符串匹配的任何模板引用,并 return 它们在查询列表中。
项目 4:组合起来
我现在有适当的函数可以在所需的键事件上执行,带有所需的参数,以及我所有输入元素引用的平面列表。
现在我只需要编写代码来完成这项工作:
focusInput(rowIdx: number, colIdx: number) {
console.log(rowIdx, colIdx);
// convert ViewChildren querylist to an array to access by index
let inputEls = this.inputs.toArray();
// get the flat index from row/cols
let flatIdx = (rowIdx * this.columns.length) + colIdx;
// get that reference from the input array and use the native element focus() method
inputEls[flatIdx].nativeElement.focus();
}
shiftFocusDown(rowIdx:number, colIdx:number) {
console.log("DOWN", colIdx, rowIdx)
// add 1 but don't go beyond my row range
rowIdx = Math.min(rowIdx + 1, this.rows.length - 1);
this.focusInput(rowIdx, colIdx);
}
shiftFocusUp(rowIdx:number, colIdx:number) {
console.log("UP", colIdx, rowIdx);
// up 1, but not less than 0
rowIdx = Math.max(0, rowIdx - 1);
this.focusInput(rowIdx, colIdx);
}
shiftFocusLeft(rowIdx:number, colIdx:number) {
console.log("LEFT", rowIdx, colIdx);
// left one column, and correct for non editable columns to left
colIdx = colIdx - 1 - this.columns.slice(0, colIdx).reverse().findIndex(c => c.editable);
// don't need edge check bc findIndex returns -1 if none found or no items, so that corrects us back to start col automatically
this.focusInput(rowIdx, colIdx);
}
shiftFocusRight(rowIdx:number, colIdx:number) {
console.log("RIGHT", rowIdx, colIdx);
// right one column, and correct for non editable columns to right
colIdx = colIdx + 1 + this.columns.slice(colIdx + 1).findIndex(c => c.editable);
// don't need edge check bc findIndex returns -1 if none found or out of range, so that corrects us back to start col automatically
this.focusInput(rowIdx, colIdx);
}
这里的代码主要是找到下一个合适的 col/row 索引,然后将 x,y 转换成平面索引,这样我就可以在我的 viewchildren 列表中找到正确的引用并调用 focus()在上面。我需要所有元素引用始终存在的原因是,否则将很难从 x、y 中找出正确的平面索引。如果您真的需要它们不在那里,那么您可以修改此逻辑以使其工作。一点也不不可能。您也可以修改它以允许 "wrapping" 非常容易地围绕行。