angular / material

Material design for AngularJS
https://material.angularjs.org/
MIT License
16.55k stars 3.39k forks source link

Feat: Add KeyCode Event Binding Directive #1953

Closed TheLarkInn closed 9 years ago

TheLarkInn commented 9 years ago

It would be great if there was a directive that would allow a user to bind a keypress event to specified key code and key code modifiers.

What exists currently on the web/ng:

angular.module("core").directive('hnEnterKey', function() {
    return function(scope, element, attrs) {
        element.bind("keydown keypress", function(event) {
            var keyCode = event.which || event.keyCode;
            if (keyCode === 13) {
                scope.$apply(function() {
                    scope.$eval(attrs.hnEnterKey);
                });

                event.preventDefault();
            }
        });
    };
});

I believe we could make something in the middle by allowing a user to add a directive, supply a key code and/or key code+modifiers, and an expression to evaluate.

Seen below is a modest Example:

<div class="container-demo">
   <input md-keycode="submitForm();" key-code="13" type="text" />

   <button>Cancel</button>
   <button>Submit</button>
</div>

Thoughts?

marcysutton commented 9 years ago

I actually talked about this for Angular in general with @bradlygreen a while back. Would be very useful.

TheLarkInn commented 9 years ago

Yeah I agree @marcysutton . I whipped up a little Plunker for the most basic approach. But this could be way more robust and am open to suggestions or approaches.

angular.module('material.components.keyCodeEvent', [
    'material.core'
  ]).directive('mdKeyCodeEvent', keyCodeEventDirective);

  function keyCodeEventDirective() {
    return {
      restrict: 'A',
      link: function($scope, $element, $attrs) {
        $element.bind("keypress", function(event) {
          var keyCode = event.which || event.keyCode;
          // console.log(keyCode);
          if (keyCode == $attrs.code) {
            $scope.$apply(function() {
              $scope.$eval($attrs.mdKeyCodeEvent, {$event: event});
            });

            event.preventDefault();
          }
        });
      }
    };
  }

Things worth considering:

TheLarkInn commented 9 years ago

@marcysutton would we want to use $parse instead of $eval for the bound expression?

ajoslin commented 9 years ago

You can get crazy and do <input ng-keypress="{ 13: enterPressed }[$event.keyCode]()">, where enterPressed is a function on the scope.

TheLarkInn commented 9 years ago

@ajoslin I thought about that and it seems very tempting. I like the flexibility that the syntax would bring to the component. Would it be better to use the same code attribute or a code-map attribute in addition? Great idea!!

marcysutton commented 9 years ago

A directive like this isn't really a Material Design thing, but rather a generic Angular thing. We could interface with it in our components, though, perhaps as a plugin.

TheLarkInn commented 9 years ago

@marcysutton thank you!!! Perhaps I'll draft something up for in angular/angular.js and see if it gets some traction.

mattclevyr commented 9 years ago

Let's make this a thing.

marcysutton commented 9 years ago

@TheLarkInn can you post a link to the issue here once you open it? I'd love to stay involved with the effort.

TheLarkInn commented 9 years ago

@marcysutton yes!!! Link can be seen below:

https://github.com/angular/angular.js/issues/11378

I'm not sure if there is a fancy way to tie issues across projects but there ya go!! 😇

ThomasBurleson commented 9 years ago

Close as not specific to Angular Material