Angular 4 关注向下箭头上的项目并滚动

Angular 4 focus on item on arrow down and scroll

我在 div *ngFor 循环中有项目,它在 selected 消息上应用 css class 'message-list-active'。

app.html

 <div  id="listText" *ngFor="let message of messages; let i=index" activeIndex = i" 
   [ngClass]="{'message-list-active': activeIndex === i  }">
      {{message.name}}
 </div>

component.ts //使用上下箭头监听键盘事件 select message

  messages;  // we have date stored here
  activeIndex = 0;


  @HostListener("document:keydown", ['$event']) 
   doSomething(event: KeyboardEvent): void {


  if (event.code == "ArrowUp" && this.activeIndex > 0) {
    this.activeIndex--

   }
  if (event.code == "ArrowDown" && this.activeIndex < this.messages.length-1) {
    this.activeIndex++

  }
 }

app.css

    #listText {
        width: auto;
        height:100%;
        overflow: auto
      }

     .message-list-active {
        margin: 0;
        padding: 15px 15px 5px 13px;
        border-radius: 0;
        background-color: #CDE6F7;
        border-style: dotted;
        border-width: 1px;
        border-bottom: 1px dotted;
         }

问题是当 selected 消息到达列表末尾时它不会滚动。所以我想要实现的是让 selected 项目始终聚焦并能够上下滚动:

这里也有类似的例子:

这是我正在尝试实现的,使用 jquery jsfiddle http://jsfiddle.net/38zR3/42/, similar question/answer 回答了这个问题,但是我如何在 Angular 4 中使用 typescript

实现这个

它将看起来像这样:

private scrollTo(_index: any) {
  let elmnt = document.getElementById(_index);
  elmnt.scrollIntoView();
   window.scrollTo(0, 0); // only if it's innerhtml
}

这将确保焦点所在的所有项目都在视图中。

在 html 中需要做类似的事情:

id={{item.uniqueID}} (focus)="scrollTo(item.uniqueID)" 确保它对于使用此函数的所有内容都是唯一的。

编辑

在 html 中尝试:id="list{{i}}"

if (event.code == "ArrowUp" && this.activeIndex > 0) {
    this.activeIndex--
    let str = `list${this.activeIndex}`;
    let elmnt = document.getElementById(str);
    elmnt.scrollIntoView();
    window.scrollTo(0, 0);
}

好的,通过自定义指令修复它 [focused]

app.html

     <div id="listText">
        <div *ngFor="let message of messages; [focused]="i === activeIndex" let i=index" activeIndex = i" 
          [ngClass]="{'message-list-active': activeIndex === i  }">
       {{message.name}}
  </div>

Focused.directive:

  import {Directive, Input, Renderer, ElementRef} from '@angular/core'

  @Directive({
   selector: '[focused]'
     })

 export class FocusedDirective {

      @Input()
      set focused(value: boolean){
         if(value){
           this.renderer.invokeElementMethod(this.elementRef.nativeElement, 'scrollIntoViewIfNeeded');
         }
    }

  constructor(private elementRef: ElementRef, private renderer: Renderer){}
   }