Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 4 focus on item on arrow down and scroll

Tags:

I have items in the div *ngFor loop which applies css class 'message-list-active' on the selected message.

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 //listen for keyboard event using arrow up and down to 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;
         }

And the problem is when selected message comes to the end of the list it will not scroll. So what I am trying to achieve is to have the selected item always focused and be able to scroll down and up:

Also similar example here:

enter image description here

Here is what I am trying to achieve this was answered using jquery jsfiddle http://jsfiddle.net/38zR3/42/, similar question/answer but how can I achieve this in Angular 4 using typescript

like image 792
AlexFF1 Avatar asked Dec 22 '17 10:12

AlexFF1


2 Answers

It will looking something like this:

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

This will ensure that ever item that's focus will be into view.

In html need to do something like:

id={{item.uniqueID}} (focus)="scrollTo(item.uniqueID)" Make sure to make it unique for everything that uses this function.

EDIT

Try an in 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);
}
like image 196
Swoox Avatar answered Sep 21 '22 12:09

Swoox


Ok so fixed it by making a custom directive [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){}
   }
like image 23
AlexFF1 Avatar answered Sep 23 '22 12:09

AlexFF1