我正在做角度项目,遇到这样的情况:我连续有一系列的div,当用户单击任何一个div时,他应该能够使用箭头键从一个div移到另一个div。
请帮助。
我尝试使用按键事件,但并没有帮助我。试图找出关于stackoverflow的类似问题,但所有答案都在jquery中,我需要在打字稿中输入。
moveCell(e){
console.log(e);
}
.container{
width: 100%;
}
.cell{
width: 100px;
float:left;
}
.cell:hover,
.cell:focus{
background: red;
}
<div class="container">
<div class="cell" (keypress)="moveCell($event)">cell 1</div>
<div class="cell" (keypress)="moveCell($event)">cell 2</div>
<div class="cell" (keypress)="moveCell($event)">cell 3</div>
<div class="cell" (keypress)="moveCell($event)">cell 4</div>
<div class="cell" (keypress)="moveCell($event)">cell 5</div>
<div class="cell" (keypress)="moveCell($event)">cell 6</div>
<div class="cell" (keypress)="moveCell($event)">cell 7</div>
<div class="cell" (keypress)="moveCell($event)">cell 8</div>
<div class="cell" (keypress)="moveCell($event)">cell 9</div>
</div>
在我的代码中,如果用户单击单元格2,则焦点应自动转到单元格2。此后,如果用户使用键盘并按箭头键,则应将焦点移至下一个/上一个单元格。
答案 0 :(得分:2)
keypress
未检测到arrow keys
,而是使用keydown
。为了获得焦点并聆听按键事件,请向div添加属性tabindex
。
对于右箭头键,您需要检查当前活动元素是否不是最后一个元素,并将焦点更改为下一个元素。
对于左箭头键,检查当前活动元素是否不是第一个元素,然后将焦点更改为上一个元素。
-HTML-
<div class="container">
<div tabindex="0" class="cell" (keydown)="moveCell($event)">cell 2</div>
<div tabindex="1" class="cell" (keydown)="moveCell($event)">cell 3</div>
<div tabindex="2" class="cell" (keydown)="moveCell($event)">cell 4</div>
<div tabindex="3" class="cell" (keydown)="moveCell($event)">cell 5</div>
<div tabindex="4" class="cell" (keydown)="moveCell($event)">cell 6</div>
<div tabindex="5" class="cell" (keydown)="moveCell($event)">cell 7</div>
<div tabindex="6" class="cell" (keydown)="moveCell($event)">cell 8</div>
</div>
-组件代码-
length: 0;
domEles;
moveCell(e){
const activeEle = document.activeElement;
const activeEleIndex = Array.prototype.indexOf.call(this.domEles, activeEle);
if(e.key == "ArrowRight" && activeEleIndex < this.length - 1 ) {
activeEle.nextElementSibling.focus();
}
if(e.key == "ArrowLeft" && activeEleIndex > 0) {
activeEle.previousElementSibling.focus();
}
}
ngOnInit() {
this.domEles = document.querySelectorAll('.container > *');
this.length = this.domEles.length;
}
Working Code
-https://stackblitz.com/edit/angular-5qxicw。
答案 1 :(得分:0)
还有一个使用指令的方法。好吧,我们的想法是,我们使用ViewChildren在app.component中获取所有包含指令的div,然后将带有指令的div发送一个事件并调用app.component的函数。所以app.component变成了
<div arrow-div (event)="handler($event)>my div</div>
<div arrow-div (event)="handler($event)>my div</div>
...
但是我们可以使用“服务”使事物更“透明”。
想象一下类似的服务
@Injectable({
providedIn: 'root',
})
export class KeyBoardService {
keyBoard:Subject<any>=new Subject<any>();
sendMessage(message:any)
{
this.keyBoard.next(message)
}
}
当按下键箭头时,我们的指令可以调用服务“ sendMessage”,并且在我们的app.component中订阅该服务。然后我们的app.component就像
<div arrow-div >my div</div>
<div arrow-div >my div</div>
<br/>
<div arrow-div >my div</div>
<div arrow-div >my div</div>
我们避免在div中使用此“ ugly”(event)=“ handler($ event)”!
好吧,该指令很简单,使用@Hostlistener侦听键,并使用renderer2添加属性“ tabindex”(要使div可聚焦,我们需要添加tabIndex)。所以
@Directive({
selector: '[arrow-div]',
})
export class ArrowDivDirective {
constructor(private keyboardService: KeyBoardService, public element: ElementRef, private render: Renderer2) {
this.render.setAttribute(this.element.nativeElement, "tabindex", "0")
}
@HostListener('keydown', ['$event']) onKeyUp(e) {
switch (e.keyCode) {
case 38:
this.keyboardService.sendMessage({ element: this.element, action: 'UP' })
break;
case 37:
this.keyboardService.sendMessage({ element: this.element, action: 'LEFT' })
break;
case 40:
this.keyboardService.sendMessage({ element: this.element, action: 'DOWN' })
break;
case 39:
this.keyboardService.sendMessage({ element: this.element, action: 'RIGTH' })
break;
}
}
}
还有我们的app.component.ts
export class AppComponent implements OnInit {
columns:number=2;
@ViewChildren(ArrowDivDirective) inputs:QueryList<ArrowDivDirective>
constructor(private keyboardService:KeyBoardService){}
ngOnInit()
{
this.keyboardService.keyBoard.subscribe(res=>{
this.move(res)
})
}
move(object)
{
const inputToArray=this.inputs.toArray()
let index=inputToArray.findIndex(x=>x.element==object.element);
switch (object.action)
{
case "UP":
index-=this.columns;
break;
case "DOWN":
index+=this.columns;
break;
case "LEFT":
index--;
break;
case "RIGTH":
index++;
break;
case "RIGTH":
index++;
break;
}
if (index>=0 && index<this.inputs.length)
inputToArray[index].element.nativeElement.focus();
}
}
请注意,如果我们要对cols和rows创建“ grid”,并使用上下键在各行之间移动,那么我将使用变量“ column”。发送“元素”以避免我们必须存储“ div集中”
您可以在stackblitz
中查看示例