Dhana
Dhana

Reputation: 1658

Using up/down arrow to focus and select list values with AngularJS

I have an input element and when its contents changes - a ul list is populated. I am able to focus on mouse over using css.

Questions:

1) How can I focus a ul > li list values using up/down arrow key ?
2) How to select a ul > li value using Enter key?

Please refer http://jsfiddle.net/3etbtfwL/458/

Upvotes: 1

Views: 4687

Answers (1)

Stanislav Kvitash
Stanislav Kvitash

Reputation: 4622

You can use ngKeydown directive on the input element to handle the keydown event and check what key was pressed (in your case 13, 38 ,40 codes) and ngClass to visually represent the currently focused list element. Here is a working example:

var app = angular.module('httpApp', [])
    .controller('httpAppCtrlr', function ($scope) {

        $scope.focusedIndex = 0;

        $scope.Change = function (item) {
            $scope.items = $.grep($scope.list, function (v) {
                if (v.name === item) {
                    return v.value;
                }
            });
            $scope.focusedIndex = 0;
        };

        $scope.selected = function (value) {
            $scope.selectedValue = value;
        };

        $scope.list = [
            {
                "name": "1",
                "value": "value1"
            }, {
                "name": "1",
                "value": "value2"
            }, {
                "name": "1",
                "value": "value3"
            }, {
                "name": "2",
                "value": "value4"
            }, {
                "name": "2",
                "value": "value5"
            }
        ];

        $scope.handleKeyDown = function($event) {
            var keyCode = $event.keyCode;
            if (keyCode === 40) {
                // Down
                $event.preventDefault();
                if ($scope.focusedIndex !== $scope.items.length - 1) {
                    $scope.focusedIndex++;
                }
            }
            else if (keyCode === 38) {
                // Up
                $event.preventDefault();
                if ($scope.focusedIndex !== 0) {
                    $scope.focusedIndex--;
                }
            }
            else if (keyCode === 13 && $scope.focusedIndex >= 0) {
                // Enter
                $event.preventDefault();
                $scope.selected($scope.list[$scope.focusedIndex].value);
            }
        };

    });
.outputLists {
    padding: 6px;
    display: block;
    cursor: pointer;
    outline: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.outoutList {
    display: block;
    z-index: 99;
    width: 30%;
    position: absolute;
    top: 36px;
    margin: -1px 0 0;
    border: 1px solid #eee;
    border-top: 0;
    padding: 0;
    background: #eee;
    -webkit-border-radius: 0 0 5px 5px;
}

.outputLists.focus {
    background: #428bca;
}
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script>

<div data-ng-app='httpApp' data-ng-controller='httpAppCtrlr'>

    <input type="text" ng-change="Change(item)" ng-model="item" placeholder="select"
           ng-keydown="handleKeyDown($event)"/>

    <ul class="outoutList" tabindex="0" ng-keydown="handleKeyDown($event)">
        <li ng-repeat="item in items" data-item="true" data-index="0" class="outputLists" 
            ng-click="selected(item.value)" ng-class="{'focus': focusedIndex == $index}" 
            ng-mouseover="$parent.focusedIndex = $index">
            {{item.value}}
        </li>
    </ul>
    <lable>
        Selected Value: {{selectedValue}}, Vocused index: {{focusedIndex}}
    </lable>
</div>

<script src="//code.jquery.com/jquery-1.10.2.js"></script>

UPDATE: To allow keyboard actions on the list element you can add tabindex to the ul and use the same ng-keydown event.

Upvotes: 2

Related Questions