jose
jose

Reputation: 143

angular material md-select to show the dropdown on focus

I have a form and has a bunch of md-selects, text fields and so on. It is a large form and the users expect to press tab and navigate through different form fields. When md-select receives focus via tab key press, it doesnt show the dropdown. An additional down arrow press is required in this case. Is there any way to get the select to display the dropdown without a mouseclick or a down key press ?

I tried adding link functions to mdSelect directive to register a click or a down key press event and it seemed to not work as well. Also, md-autocomplete has a different look and feel altogether, so it doesnt go along with the other input containers.

Additionally is there anyway to get the select dropdown to appear below the input area.

I like the code to be clean and prefer not to use any jquery functions on it. Thanks in advance.

Upvotes: 4

Views: 7126

Answers (3)

sergio0983
sergio0983

Reputation: 1268

Although already answered, I prefered to use another approach with decorators, and wanted to share it, since I don´t like too much to declare multiple directives to control behavior of a single element.

.config(function($provide) {
    $provide.decorator('mdSelectDirective', function($delegate) {
        var directive = $delegate[0];
        var originalController = directive.controller;

        var decoratedController = function($scope, $element){
            $element.bind("keyup", function(ev){
                if ( ev.keyCode == 9 ){ //Tab key code
                    $element.triggerHandler('click');
                }
            });

            originalController($scope, $element);
        }

        directive.controller = decoratedController;

        return $delegate;
    });
})

Upvotes: 1

jose
jose

Reputation: 143

Thanks to Tim Harker for the guidance.

I have modified the directive a bit to hide the exposed scope variables and the mdOnClose so that the developer can achieve it in one additional attribute.

plnkr.co/edit/m6LGjVronWR2dMQrwGFn?p=preview.

var app = angular.module('app', ['ngMaterial']);
    app.directive('myOnFocus', function() {
        return {
            scope: true,
            restrict: 'A',
            link: function(scope, elem, attr, ctrl) {
                scope.showOptions = true;
                if ((attr['mdOnClose'])) {
                    attr['mdOnClose'] = "showOptions=false;" + (attr['mdOnClose']);
                } else {
                    (attr['mdOnClose']) = "showOptions=false;"
                }

                elem.bind('focus', function() {
                    if (scope.showOptions) {
                        console.log(scope, elem, attr, ctrl)
                        elem.triggerHandler('click');
                    }
                });

                elem.bind('blur', function() {
                    scope.showOptions = true;
                });
            }
        };
    });

Upvotes: 2

Tim Harker
Tim Harker

Reputation: 2407

Here's a screen shot of the results:

angular material md-select to show the dropdown on focus

Here's the key HTML:

<md-input-container md-no-float flex="30">
  <md-select name="favoriteColor" ng-model="color" placeholder="Pick a Color" 
             ng-init="showOptions=true" 
             my-on-focus="showOptions" 
             md-on-close="showOptions=false">
    <md-option value="red">Red</md-option>
    <md-option value="blue">Blue</md-option>
    <md-option value="green">Green</md-option>
  </md-select>
</md-input-container>

Note the ng-init, my-on-focus, and md-on-close attributes.

Here's the AngularJS directive:

app.directive('myOnFocus', function() {
  return {
    scope: true,
    restrict: 'A',
    link: function(scope, elem, attr, ctrl) {
      elem.bind('focus', function() {
        if (scope[attr.myOnFocus]) {
          elem.triggerHandler('click');
        }
      });
      elem.bind('blur', function() {
        scope[attr.myOnFocus] = true;
      });
    }
  };
});

The trick is to set the showOptions variable to false when the select is closed so it doesn't open again until blur is run in the directive.

Here's the CSS to get the select dropdown to appear below the input area:

md-select-menu {
  margin-top: 50px;
}

Finally, here's a working Plunker, http://plnkr.co/edit/FD5u78pC3HbO9UwUOKXR?p=preview.

Hope it helps. Let me know if you have any questions.

Upvotes: 4

Related Questions