0

In my Angular 7 application, I have have over 5000 elements in a tree view. I need to access the DOM element that has been selected, so I can use something like scrollIntoView. Basically my pseudo code would look like this:

if selected element is not visible call scrollIntoView on the element 

Problem is, I need to call this every time the keyboard is pressed (arrows up and down). I have tried passing in the $event to find the previous element, next element, and so on, so I can simply call scrollIntoView() on that element, but I don't think that's a very good idea. It involves a lot of recursion (because the tree view is nested) and my HTML can never change (unless I update the code as well).

Is it possible to set ViewChild() based on a condition? That way I can simply do this.selectedElement.nativeElement.scrollIntoView() or something like that. Unless there's a better idea?

4
  • Maybe this link will help you : stackoverflow.com/questions/53149659/…. Commented Nov 6, 2018 at 9:30
  • @ShashikantDevani Except I only need my one and only element. Commented Nov 6, 2018 at 9:31
  • Then you can pass index from ngFor Commented Nov 6, 2018 at 9:32
  • @ShashikantDevani What would that help? Commented Nov 6, 2018 at 9:33

1 Answer 1

2

Well that's not very clear, but if I got it correctly, you can use @ViewChildren, which is basically several @ViewChild.

This stackblitz shows how you can use it, and as you can see, it's very easy to use.

import { Component, QueryList, ElementRef, ViewChildren } from '@angular/core'; @Component({ selector: 'my-app', template: `<hello name="{{ name }}"></hello> <div *ngFor="let index of [1, 2, 3, 4, 5]" (mouseover)="hovered(divs)" #divs> This is the div n° {{ index }} </div>`, styleUrls: [ './app.component.css' ] }) export class AppComponent { @ViewChildren('divs') divs: QueryList<ElementRef<HTMLDivElement>>; name = 'Angular'; hovered(div: HTMLDivElement) { // Getting from the query list const corresponding = this.divs.find(_div => _div.nativeElement === div).nativeElement; // they are the same console.log(corresponding); console.log(corresponding === div); console.log(div); } } 
Sign up to request clarification or add additional context in comments.

8 Comments

Problem is I only want ONE ViewChild (or ViewChildren). ViewChildren could work, but I need a way to conditionally say "if my viewchild has xxx property", that I can set somehow, then it could work. I just need ONE element, which is the selected one.
Well as you can see in the stackblitz, it only returns a single element, which contains anything you have declared on it (for instance, an active class).
Okay, let me break it down a bit more, so it's easier to understand. Look at this StackBlitz: stackblitz.com/edit/angular-j7ovfn - The "corresponding" element is never updated to the new one, even though I change the selected to a new one. To test it out, click on the first element in the list and press on your down arrow key.
That's because your code isn't supposed to do what you expect it to do. In this stackblitz, you can see that it's workign pretty well (I didn't secure the arrow keys so don't click on the first or last item to test it out !)
What about nested elements? As I explained I have in the OP. Working with simple HTML where I only have DIVs right after each other is easy enough. But when it comes to nested elements (think about ul and li tags), it's a whole different story. Here's an example (only arrow down works in the demo) where I have nested ul and li tags: stackblitz.com/edit/angular-eavqd6 (a bit different than the other StackBlitz you provided, but it should make sense).
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.