Hacker
Hacker

Reputation: 7896

make enter key select the dropdown element after user traverses using keys

I have a custom angular 4 dropdown element like below.

<div class="se-box se-box-val newMarginBottom">
    <section class="custom-selectbox-wrap" tabindex="0">
        <span tabindex="-1" class="fa fa-sort-desc fa-2x custom-selectbox-arrow newArrowClass" id="quick-search-drop2" (click)="SearchDropDown =!SearchDropDown;"></span>
        <input (keydown)="eventHandler($event)" readonly="readonly" type="text" id="correspondSelectTime" name="correspondSelectTime" class="custom-selectbox newHeightClass" (click)="SearchDropDown =!SearchDropDown;" [(ngModel)]="SearchDropDownText" />
        <div class="lfg-ca-chosen-drop quick-search-drop" *ngIf="SearchDropDown" tabindex="-1">
            <ul class="chosen-results custom-selectbox-list-cont customized-dropDown-active">
                <li tabindex="0" *ngFor="let option of mockdata;let idx=index" #dropdown name=idx title="{{option.text}}" class="active-result" [ngClass]="{'displaynone':SearchDropDownText==option.text }" (focus)="focused(option)" (click)="selectDropdown(option)">{{option.text}}</li>
            </ul>
        </div>
    </section>
</div>


import {
    Component,
    ElementRef,
    OnInit,
    Input,
    Output,
    EventEmitter,
    DoCheck,
    KeyValueDiffers
} from '@angular/core';

@Component({
    selector: 'app-simple-dropdown',
    templateUrl: './simple-dropdown.component.html',
    styleUrls: ['./simple-dropdown.component.styl'],
    host: {
        '(document:click)': 'onwindowClick($event)',
    },
})
export class SimpleDropdownComponent implements OnInit {

    @Input() mockdata: object;
    @Output() dropdownData: EventEmitter < any >= new EventEmitter();
    SearchDropDown: boolean;
    SearchDropDownText: string;
    SearchPlaceHolder: string;
    SearchDropDownVal: string;
    differ: any;
    focusedIdx: number;
    constructor(private differs: KeyValueDiffers, private _eref: ElementRef) {
        this.differ = differs.find({}).create(null);
    }

    ngOnInit() {
        this.SearchDropDown = false;
        this.focusedIdx = 0;
    }
    eventHandler(event) {
        // console.log(event, event.keyCode);

        // console.log(this.SearchDropDown)
        console.log(event.keyCode);
        if (event.keyCode == 40) {
            event.stopPropagation();
            this.SearchDropDown = true;
            console.log(event);
            // console.log(event.srcElement.nextElementSibling)
            // console.log("in event")
        }
    }
    handleKeyEvent(event: Event): void {
        this.focusedIdx++;
        console.log('working here');
    }

    onwindowClick(event) {
        if (!this._eref.nativeElement.contains(event.target))
            this.SearchDropDown = false;
    }
    ngDoCheck() {
        var changes = this.differ.diff(this.mockdata);
        if (changes) {
            this.SearchDropDownText = this.mockdata[0].text;
            this.SearchDropDownVal = this.mockdata[0].value;
            this.SearchPlaceHolder = this.mockdata[0].placeHolder;;
        }
    }

    selectDropdown(option) {
        this.SearchDropDown = false;
        this.SearchDropDownText = option.text;
        this.SearchDropDownVal = option.value;
        this.SearchPlaceHolder = option.placeHolder;
        let data = {
            "SearchDropDownText": this.SearchDropDownText,
            "SearchDropDownVal": this.SearchDropDownVal,
            "SearchPlaceHolder": this.SearchPlaceHolder
        };
        this.dropdownData.emit(data);


    }



}

This works perfectly fine. But i am not able to a add a enter key event so that when user uses up and down arrow and uses enter to select the li element.

Upvotes: 1

Views: 4418

Answers (1)

Nehal
Nehal

Reputation: 13297

You can extend your function to handle enter:

eventHandler(event) {
    // console.log(event, event.keyCode);
    // console.log(this.SearchDropDown)
    // console.log(event.keyCode);
    if (event.keyCode == 40) {
        event.stopPropagation();
        this.SearchDropDown = true;
        // console.log(event);

        if(this.focusedIdx >= -1 && (this.focusedIdx < this.mockdata.length)){
          this.focusedIdx++;
        }
        else{
          this.focusedIdx = 0;
        }

        // console.log(event.srcElement.nextElementSibling)
        // console.log("in event")
    }
    if (event.key == "ArrowUp") {
        event.stopPropagation();
        this.SearchDropDown = true;
        // console.log(event);

        if(this.focusedIdx > -1 && (this.focusedIdx != 0)){
          this.focusedIdx--;
        }
        else{
          this.focusedIdx = this.mockdata.length - 1;
        }

        // console.log(event.srcElement.nextElementSibling)
        // console.log("in event")
    }

    if (event.code == "Enter" && this.focusedIdx > -1){
        event.stopPropagation();
        this.selectDropdown(this.mockdata[this.focusedIdx]); 
    }
}

setIndex(index){
   this.focusedIdx = index;
}

resetIndex(){
   this.focusedIdx = -1;
}

html change:

<li tabindex="0" 
  *ngFor="let option of mockdata;let idx=index" 
  #dropdown name=idx 
  class="active-result" 
  ngClass]="{'highlight-row' :  idx == focusedIdx }"
  (mouseenter)="setIndex(idx)" 
  (mouseleave)="resetIndex()"
  (click)="selectDropdown(option)">
  {{option.text}}
</li>

css for highlight:

.highlight-row{
  background-color: #5bc0de;
  border-color: #46b8da;
  color: #FFFFFF;
}

demo

Upvotes: 2

Related Questions