Initiate the typeahead drop down menu by pressing the downward key and then navigate through the options within the drop down

Utilizing the bootstrap typeahead feature within my angular project has been a game-changer. I needed a way to activate the typeahead drop down by pressing the down key when no text had been entered yet. By following guidance from this resource, I was able to successfully implement this functionality. You can view a demonstration of it here.

However, the downside is that by enabling the drop down with the down key, it overrides the default behavior of navigating through the options.

index.html

<!DOCTYPE html>
<html ng-app="plunker">

  <head>
    <link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet" />
    <link href="style.css" rel="stylesheet" />
    <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.2/angular.js"></script>
    <script src="ui-bootstrap-tpls-0.10.0.js"></script>
    <script src="script.js"></script>
  </head>

  <body>
    <div class="container-fluid" ng-controller="TypeaheadCtrl">
      <input type="text" ng-keydown="show($event)" ng-trim="false" ng-model="selected" empty-typeahead typeahead="state for state in states | filter:$viewValue:stateComparator" class="form-control" />
      <pre ng-show="opened">Model: {{selected | json}}</pre>
    </div>
  </body>

</html>

script.js

(function () {
  var secretEmptyKey = '[$empty$]'

  angular.module('plunker', ['ui.bootstrap'])
    .directive('emptyTypeahead', function () {
      return {
        require: 'ngModel',
        link: function (scope, element, attrs, modelCtrl) {
          // this parser run before typeahead's parser
          modelCtrl.$parsers.unshift(function (inputValue) {
            var value = (inputValue ? inputValue : secretEmptyKey); // replace empty string with secretEmptyKey to bypass typeahead-min-length check
            modelCtrl.$viewValue = value; // this $viewValue must match the inputValue pass to typehead directive
            return value;
          });

          // this parser run after typeahead's parser
          modelCtrl.$parsers.push(function (inputValue) {
            return inputValue === secretEmptyKey ? '' : inputValue; // set the secretEmptyKey back to empty string
          });
        }
      }
    })
    .controller('TypeaheadCtrl', function($scope, $http, $timeout) {
      $scope.selected = undefined;
      $scope.states = ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado', 'Connecticut', 'Delaware', 'Florida', 'Georgia', 'Hawaii', 'Idaho', 'Illinois', 'Indiana', 'Iowa', 'Kansas', 'Kentucky', 'Louisiana', 'Maine', 'Maryland', 'Massachusetts', 'Michigan', 'Minnesota', 'Mississippi', 'Missouri', 'Montana', 'Nebraska', 'Nevada', 'New Hampshire', 'New Jersey', 'New Mexico', 'New York', 'North Dakota', 'North Carolina', 'Ohio', 'Oklahoma', 'Oregon', 'Pennsylvania', 'Rhode Island', 'South Carolina', 'South Dakota', 'Tennessee', 'Texas', 'Utah', 'Vermont', 'Virginia', 'Washington', 'West Virginia', 'Wisconsin', 'Wyoming'];

      $scope.stateComparator = function (state, viewValue) {
        return viewValue === secretEmptyKey || (''+state).toLowerCase().indexOf((''+viewValue).toLowerCase()) > -1;
      };

      $scope.show = function (e) {
        var keyCode = e.keyCode || e.which;
        if (keyCode == 40) { //If it's the down key
            $timeout(function () {
                $(e.target).triggerHandler('input');
            });
        }
    };

    });
}());

Is there any way to have the drop down open on the first click and then navigate to the next option on subsequent clicks?

Answer №1

After some troubleshooting, I managed to resolve the issue by incorporating an if statement when displaying the typeahead drop down menu.

$scope.show = function (e) {
    if($scope.selected === undefined){
      var keyCode = e.keyCode || e.which;
      if (keyCode == 40) { //Checking for the down key press
        $timeout(function () {
            $(e.target).triggerHandler('input');
        });
     }
   }
};

I also made sure to set undefined in $scope.selected if the user had not selected any item:

$scope.clearIfEmpty = function () {
    if($scope.selected !== undefined && $scope.selected.length === 0){
      $scope.selected = undefined;  
    }
}

See the solution in action here.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Text loaded dynamically is not remaining within the div

I am experiencing an issue with dynamically loaded content where Images work fine, but Links and Text are not displaying properly. For reference, you can view the problem in this JSFiddle: http://jsfiddle.net/HRs3u/1/ I suspect that it might be related t ...

Issues with column alignment in data tables with fixed headers

While working with an angular data table, I implemented a fixed header property that code looked like this: $scope.table.dataTable($scope.gridOpts); new $.fn.dataTable.FixedHeader($scope.table); The fixed header worked well as it stayed at the top of ...

What is the best way to reverse an EJS forEach loop?

Here is my ejs code to display images and names from my database. How can I reverse the array order to show the images and names in reversed order? <% posts.reverse().forEach(function(post){ %> <div class="col-md-3 col-sm-6"> ...

Why is it not possible to declare an interface or type within a TypeScript class?

I am struggling to define interface | type within a TypeScript class. Here is the code snippet: class MyClass { interface IClass { name: string, id: string } } However, I keep encountering this error: Unexpected token. A constructo ...

"Unspecified" following the execution of eval

Received this JSON object from backend services [{"date":"2014-02-06","fontSize":14,"bgColor":"#000000","fontType":"Arial","userId":1012}] Trying to extract and utilize the elements within the JSON object in my code, but encountering undefined when using ...

Concealing certain elements within a loop using a "show more" button

In my PHP code, I am utilizing a foreach loop in the following manner: <div class="items"> @foreach($results as $details) <div class="col s2 l2"> {{ $details }} </div></div> My approach involves using the blade templating feature ...

Specify the content type header in IE request with AJAX

Is it feasible to specify the http content-type request header as 'application/json' while sending a cross domain jquery ajax http request from Internet Explorer? We are attempting to access a REST WCF service that relies on the content type pro ...

Displaying 'bound m' in an Angular ng-repeat loop

When connecting to a REST API, I utilize the restangular library. To manage API calls, I have created a ProductService.js file which contains the following code: 'use strict'; angular.module('app').service('ProductService', ...

Using ngTouch for ng-click events on the body element can cause issues with links and input fields on mobile

Seeking assistance with a unique issue I am facing on my app-like website. I have implemented a swipable menu but I want it to close whenever the user taps outside the menu. I have tried using ngTouch for swiping and attached ng-click="menuToggled = false" ...

Next step is transferring form data from React to Node server

I am currently working on an EmailList component in react that interacts with a server-side Node.js script called EmailServer.js. This script uses Nodemailer to send emails, and I have successfully set it up to send emails with predefined subject lines and ...

Using Typescript to declare types for an object that is capable of generating an outcome

If I have an object structured like this let obj = { property1:()=>{ return Date()} // for example, it doesn't have to be a date property2:()=>{ return 1} } Now, I want to convert this to the following type structure { property1: ...

Attempting to authenticate user with Node.js and MongoDB integration

I have been attempting to log in a user, but I keep encountering the error "user is not defined". I've made sure to use both upper and lowercase variations of "user/User", yet it continues to show up as undefined. var mongoose = require("mongoose") va ...

If the data attribute of the div ID is equal to 1 in jQuery, then

Using a jQuery plugin, I have created some "3-D stack divs". Each div has its own unique id, and the active div is marked with data-position="1", while inactive divs are marked with data-position="2" or data-position="3". Now, how can I create an if-else ...

Using jQuery to toggle the visibility of select options for multiple elements

Hey there, I've got this code snippet that effectively shows and hides elements based on a selected option. It works well with one element, but when I try to use it with multiple elements, it doesn't function correctly. How can I tweak it so that ...

What could be causing the page to automatically scroll to the bottom upon loading?

My experience with this bootstrap/jquery page in Firefox (v39, latest updates installed) has been unusual as it always seems to jump to the bottom of the page upon clicking. Upon inspecting the code, I couldn't find any JavaScript responsible for thi ...

What is the best way to use jQuery ajax to send various row identifiers when updating table data on another PHP page by selecting checkboxes?

When I select both of the green checkboxes, only the most recent table id is sent. The code below includes both the checkbox markup and jQuery function. Checkbox: <div class='md-checkbox has-success'> <input type='checkbox&apo ...

An error has occurred: Semantic Problem. Surprise Token :?

Trying my hand at some AJAX using jQuery, but I've hit a roadblock. When checking Safari's inspector, I'm seeing errors like Semantic Issue and Unexpected Token :. Is this just a silly mistake on my part? It seems to be related to the data ...

The gap separating the three columns in the DIVs structure

Here is an example that I need The images are being loaded from a MySQL while loop, and I want the spacing between them to be such that the left column and right column touch each side with the middle image centered. Just like in the picture :D This is m ...

The issue of notifications not displaying in a Cordova iOS app due to Device.uuid plugins

Having an issue with my Cordova iOS app. I rely on the UUID functionality frequently, but it seems to be malfunctioning. The app gets stuck at the alert that displays it. onDeviceReady: function() { alert("On device Ready"); // This is working fine ...

Utilizing shared code amongst React components

There are several components with methods similar to the ones below: class Header extends Component { sidebarToggle(e) { e.preventDefault(); document.body.classList.toggle('sidebar-hidden'); } sidebarMinimize(e) { e.preventDe ...