繁体   English   中英

如何在按下左右箭头键时将箭头键焦点设置在这些按钮上?

[英]How do i set arrow key focus on these button in angular while pressing the left and right arrow keys?

在这里,当我向左和向右按箭头键时,它没有聚焦,或者我无法使用箭头键导航或选择这些按钮,但是当调整这些键码的值时,它会根据按下的键打印,我需要知道如何获得按下箭头键时关注html,以便可以使用箭头键导航按钮,如果有人可以为我提供解决方案,那将是一个很大的帮助。

组件.html

 <ng-template #content let-modal>
 <div class="modal-header">
 <h3 class="modal-title">Accept Offer</h3>
 </div>
 <div class="modal-body">
 <p>Do you really want to accept the offer?</p>
 </div>
 <div class="modal-footer>
 <button type="submit" class="btn btn-primary tab" (click)="onAcceptOffer()" arrow-div>Submit</button>
    <button type="button" class="btn btn-secondary tab" (click)="modal.dismiss('Crossclick');
   isClicked=false" arrow-div>Cancel</button></div>
 </ng-template>

服务.ts

export class KeyBoardService {
  keyBoard:Subject<any>=new Subject<any>();
  sendMessage(message:any)
  {
    this.keyBoard.next(message)
  }
}

指令.ts

@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;
    }
  }
}

组件.ts

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();
    }
  }

我想代码来自这个SO

这种方法的“问题”是您应该先关注一个 HTML 元素,然后才能使用箭头键。

我们可以采取另一种方法:服务订阅 document.fromEvent('document')

想象一下像这样的服务

import {map,filter,tap} from 'rxjs/operators'
@Injectable({
  providedIn: 'root',
})
export class KeyBoardService {
  keyBoard:Subject<any>=new Subject<any>();
  subscription:Subscription
  
  sendMessage(message:any)
  {
    this.keyBoard.next(message)
  }
  init()
  {
    if (!this.subscription)
      this.subscription=fromEvent(document,'keydown').pipe(
        filter((e:Event)=>{
          const el=document.activeElement
          const ev=(e as KeyboardEvent)

          //only want if the key is an arrow
          const isArrow=ev.keyCode>=37 && ev.keyCode<=40

          //and is the "body" or is arrow down and we are not
          //in a select or is an "arrow-div"
          return isArrow && (el.tagName== 'body' || 
                            (ev.keyCode==40 && el.tagName!='SELECT') || 
                            el.getAttribute('arrow-div')==='')
        }),
        map(e=>{
        const obj={element:document.activeElement,action:null}
        switch ((e as KeyboardEvent).keyCode) {
          case 38:
            obj.action='UP' 
            break;
          case 37:
            obj.action='LEFT' 
            break;
          case 40:
            obj.action='DOWN'
            break;
          case 39:
            obj.action='RIGTH' 
            break;
        }
        return obj
      })).subscribe(res=>{
        this.sendMessage(res)
      })
  }
  destroy()
  {
    this.subscription.unsubscribe()
    this.subscription=null;
  }
}

还有一个指令

@Directive({
  selector: '[arrow-div]',
})
export class ArrowDivDirective {
  element:HTMLElement
  constructor(private keyboardService: KeyBoardService, 
        private el: ElementRef, private render: Renderer2) {
    this.render.setAttribute(this.el.nativeElement, "tabindex", "0")
    this.element=this.el.nativeElement;
  }
}

看,在这种情况下我们不使用@HotListener,并且“元素”属性是HTMLElement(不是nativeElement)

我们可以在我们的组件中使用

@ViewChildren(ArrowDivDirective) inputs: QueryList<ArrowDivDirective>;

  constructor(private keyboardService: KeyBoardService) {}
  ngOnInit() {
    this.keyboardService.init();
    this.keyboardService.keyBoard.subscribe((res) => {
      this.move(res);
    });
  }
  move(object: any) {
    const inputToArray = this.inputs.toArray();
    let index = inputToArray.findIndex((x) => x.element == object.element);
    if (index < 0) index = 0;
    else {
      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.focus();
    }
  }
  ngOnDestroy() {
    this.keyboardService.destroy();
  }

看到有必要“初始化”我们的服务(开始订阅 fromEvent(document,'keydown'),并在 ngOnDestroy 中删除订阅

新的堆栈闪电战

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM