starlight
starlight

Reputation: 785

How to focus and navigate li elements in Angular 4?

I am trying to make a custom select option in Angular 4. But struck up unsure how to select the li options when focused in the input element.

Here's my html code:

<div class="input-container">
     <input type="text" id="iLocation"
               (focus)="onLocationFocus()"
               (blur)="onLocationBlur()">
     <span class="underline"></span>
     <label for="iLocation">Preferred Type</label>

     <div class="options-container" tabindex="0" #optionsContainerRef>
        <ul>
           <li *ngFor="let loc of locationOptions">{{loc.option}}</li>
        </ul>
     </div>
</div>

and here's my component typescript:

locationOptions = [{icon: 'school', option: 'School'}, {icon: 'home', option: 'Home'}];
@ViewChild("optionsContainerRef") optionsContainerRef: ElementRef;
constructor(private renderer: Renderer2) { }
    onLocationFocus() {
      this.renderer.setAttribute(this.optionsContainerRef.nativeElement.children[0].children[0], 'focus', 'true');
    }
    onLocationBlur() {}

Even though, the renderer adds the focus="true" element, the li element is not getting focused. I have written css code li background-color when focused, but the element isn't getting focused and the color isn't changing.

The other issue I am struck is like how to navigate through the li elements using keyboard up and down arrows. What would be the effective way to do it in angular 4? I have seen this reference, but unsure how would I do it in angular.

Please guide and help me out with this issues.

Upvotes: 2

Views: 3760

Answers (1)

Dean Chalk
Dean Chalk

Reputation: 20461

Rather than using focus, use ngClass instead - like this:

in your component class:

  locationOptions = [{ icon: 'school', option: 'School' }, { icon: 'home', option: 'Home' }];
  public focusElement: number = -1;
  constructor() { }
  onLocationFocus() {
    this.focusElement = 0;
  }
  onLocationBlur() {
    this.focusElement = -1;
  }

  onArrowUp() {
    if (this.focusElement > 0) {
      this.focusElement--;
    }
  }

  onArrowDown() {
    if (this.focusElement <= this.locationOptions.length - 2) {
      this.focusElement++;
    }
  }

Then the template looks like this:

<input type="text" id="iLocation"
               (focus)="onLocationFocus()"
               (blur)="onLocationBlur()"
               (keydown.ArrowUp)="onArrowUp()"
               (keydown.ArrowDown)="onArrowDown()">
     <span class="underline"></span>
     <label for="iLocation">Preferred Type</label>

     <div class="options-container">
        <ul>
            <li #item [ngClass]="{'focus-background': focusElement == item.tabIndex}"
              *ngFor="let loc of locationOptions; let i = index" tabIndex="{{i}}">
             {{loc.option}} </li>
        </ul>
     </div>

and a little CSS like this

.focus-background {
  background-color: lightblue;
}

Upvotes: 6

Related Questions