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){}
}
我在 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){}
}