Wie verwende ich ein Tastendruckereignis in AngularJS?


410

Ich möchte das Ereignis zum Drücken der Eingabetaste im Textfeld unten abfangen. Um es klarer zu machen, benutze ich a, ng-repeatum den Körper zu bevölkern. Hier ist der HTML:

<td><input type="number" id="closeqty{{$index}}" class="pagination-right closefield" 
    data-ng-model="closeqtymodel" data-ng-change="change($index)" required placeholder="{{item.closeMeasure}}" /></td>

Das ist mein Modul:

angular.module('components', ['ngResource']);

Ich verwende eine Ressource zum Auffüllen der Tabelle und mein Controller-Code lautet:

function Ajaxy($scope, $resource) {
//controller which has resource to populate the table 
}

1
Befindet sich die Eingabe in einem Formular?
Callmekatootie

1
nein .. es ist in einem Tisch !!
Venkata Tata

Antworten:


808

Sie müssen Folgendes hinzufügen directive:

Javascript :

app.directive('myEnter', function () {
    return function (scope, element, attrs) {
        element.bind("keydown keypress", function (event) {
            if(event.which === 13) {
                scope.$apply(function (){
                    scope.$eval(attrs.myEnter);
                });

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

HTML :

<div ng-app="" ng-controller="MainCtrl">
    <input type="text" my-enter="doSomething()">    
</div>

7
@DerekAdair Die Direktive bindet an die keydownund keypressEreignisse des Elements, dem sie zugeordnet ist. Wenn das Ereignis empfangen wird, wird der angegebene Ausdruck innerhalb eines $applyBlocks ausgewertet .
Pete Martin

7
Sicherer, den Schlüssel so zu definieren: var key = typeof event.which === "undefined" ? event.keyCode : event.which;Solange event.which nicht von jedem Browser verwendet wird. Siehe Kommentare hier: stackoverflow.com/a/4471635/2547632
Gabriel

3
Ich würde auch hinzufügen keyup im
Bindetest

59
Beachten Sie auch, dass die Verwendung des Präfixes ng nicht empfohlen wird, da dies mit zukünftigen ng- * -Anweisungen in Konflikt geraten kann. Verwenden Sie stattdessen Ihre eigenen
Marius Balčytis

3
Vergessen Sie nicht, Ihre Bindungen zu zerstören: scope. $ On ('$ destroy', function () {element.unbind ('keydown');})
nawlbergs

345

Eine Alternative ist die Verwendung der Standardrichtlinie ng-keypress="myFunct($event)"

Dann können Sie in Ihrem Controller:

...

$scope.myFunct = function(keyEvent) {
  if (keyEvent.which === 13)
    alert('I am an alert');
}

...

18
Um anderen Menschen etwas Zeit zu sparen, ng-keypressscheint es nicht Teil von Angular 1.0.x zu sein ui-keypress(mit leicht unterschiedlicher Aufrufsemantik
Cebjyre

1
Ich denke, der obige Kommentar zielte auf eine andere Antwort ab. (Nur als Referenz.)
Cornelius

Martin, das ist eigentlich die Funktion eines Controllers: UI-Ereignisse zu behandeln.
Trevor de Koekkoek

5
Besser noch, verwenden Sie ngKeypress und übergeben Sie das $ -Ereignis an einen benutzerdefinierten Filter.
Martin

7
Beste Antwort +1. Warum sollte ich meine eigene Direktive erstellen, falls es eine gibt, die bereits in Angular enthalten ist?
bFunc

179

Mein einfachster Ansatz mit nur eckiger eingebauter Direktive:

ng-keypress, ng-keydownOder ng-keyup.

Normalerweise möchten wir Tastaturunterstützung für etwas hinzufügen, das bereits per ng-click verarbeitet wurde.

zum Beispiel:

<a ng-click="action()">action</a>

Fügen wir nun die Tastaturunterstützung hinzu.

Auslösen durch Eingabetaste:

<a ng-click="action()" 
   ng-keydown="$event.keyCode === 13 && action()">action</a>

durch Leertaste:

<a ng-click="action()" 
   ng-keydown="$event.keyCode === 32 && action()">action</a>

durch Leerzeichen oder Eingabetaste:

<a ng-click="action()" 
   ng-keydown="($event.keyCode === 13 || $event.keyCode === 32) && action()">action</a>

wenn Sie in einem modernen Browser sind

<a ng-click="action()" 
   ng-keydown="[13, 32].includes($event.keyCode) && action()">action</a>

Weitere Informationen zu keyCode:
keyCode ist eine veraltete, aber gut unterstützte API. Sie können stattdessen $ evevt.key im unterstützten Browser verwenden.
Weitere Informationen finden Sie unter https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key


1
Das Geheimnis ist die Bedingung vor der auszuführenden Methode $ event.which === 13 && action () - danke!
user12121234

1
'$ event.which' funktioniert bei mir nicht, aber ich habe '$ event.keyCode' gefunden, das funktioniert.
Karl Adler

event.which ist in IE <9 bei Keydown und Keyup undefiniert.
Eric Chen

2
"alte Browser wie IE9" .. hätte nie gedacht, dass dieser Tag kommen wird :)
Mihnea Belcin

1
Warum hat hier niemand die Code-Schnipsel aktualisiert, um $ event.keyCode zu verwenden? Ich würde es selbst bearbeiten, aber ich kann es aus irgendeinem Grund nicht.
Nathan Hazzard

102

Eine weitere einfache Alternative:

<input ng-model="edItem" type="text" 
    ng-keypress="($event.which === 13)?foo(edItem):0"/>

Und die ng-ui-Alternative:

<input ng-model="edItem" type="text" ui-keypress="{'enter':'foo(edItem)'}"/>

9
ng-ui es ist mehrdeutig, stattdessen sollten Sie "UI.Utils" sagen oder den Link teilen: angular-ui.github.io/ui-utils
Paulo Oliveira

ui-utils scheint veraltet zu sein
cafesanu

19

Folgendes habe ich herausgefunden, als ich eine App mit einer ähnlichen Anforderung erstellt habe: Es ist nicht erforderlich, eine Direktive zu schreiben, und es ist relativ einfach zu sagen, was sie tut:

<input type="text" ng-keypress="($event.charCode==13)?myFunction():return" placeholder="Will Submit on Enter">

3
Einfach und effektiv.
Xplouder

15

Sie können ng-keydown = "myFunction ($ event)" als Attribut verwenden.

<input ng-keydown="myFunction($event)" type="number">

myFunction(event) {
    if(event.keyCode == 13) {   // '13' is the key code for enter
        // do what you want to do when 'enter' is pressed :)
    }
}

5

html

<textarea id="messageTxt" 
    rows="5" 
    placeholder="Escriba su mensaje" 
    ng-keypress="keyPressed($event)" 
    ng-model="smsData.mensaje">
</textarea>

controller.js

$scope.keyPressed = function (keyEvent) {
    if (keyEvent.keyCode == 13) {
        alert('presiono enter');
        console.log('presiono enter');
    }
};

3

Sie können es auch auf einen Controller in einem übergeordneten Element anwenden. In diesem Beispiel können Sie eine Zeile in einer Tabelle durch Drücken der Aufwärts- / Abwärtspfeiltasten hervorheben.

app.controller('tableCtrl', [ '$scope', '$element', function($scope, $element) {
  $scope.index = 0; // row index
  $scope.data = []; // array of items
  $scope.keypress = function(offset) {
    console.log('keypress', offset);
    var i = $scope.index + offset;
    if (i < 0) { i = $scope.data.length - 1; }
    if (i >= $scope.data.length) { i = 0; }
  };
  $element.bind("keydown keypress", function (event) {
    console.log('keypress', event, event.which);
    if(event.which === 38) { // up
      $scope.keypress(-1);
    } else if (event.which === 40) { // down
      $scope.keypress(1);
    } else {
      return;
    }
    event.preventDefault();
  });
}]);


<table class="table table-striped" ng-controller="tableCtrl">
<thead>
    <tr>
        <th ng-repeat="(key, value) in data[0]">{{key}}</th>
    </tr>
</thead>
<tbody>
    <tr ng-repeat="row in data track by $index" ng-click="draw($index)" ng-class="$index == index ? 'info' : ''">
        <td ng-repeat="(key, value) in row">{{value}}</td>
    </tr>
</tbody>
</table>


3

Ich versuche es

ng-keypress="console.log($event)"
ng-keypress="alert(123)"

habe nichts für mich getan.

Seltsamerweise funktioniert das Beispiel unter https://docs.angularjs.org/api/ng/directive/ngKeypress , das ng-keypress = "count = count + 1" ausführt.

Ich habe eine alternative Lösung gefunden, bei der durch Drücken der Eingabetaste der ng-Klick der Schaltfläche aufgerufen wird.

<input ng-model="..." onkeypress="if (event.which==13) document.getElementById('button').click()"/>
<button id="button" ng-click="doSomething()">Done</button>

ng-keypress="console.log('foo')"hat auch bei mir nicht funktioniert, aber wenn du es tust ng-keypress="fooMethod()"und in deinem Controller $scope.fooMethod = function() { console.log('fooMethod called'); }funktioniert.
GraehamF

3
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
Informe your name:<input type="text" ng-model="pergunta" ng-keypress="pressionou_enter($event)" ></input> 
<button ng-click="chamar()">submit</button>
<h1>{{resposta}}</h1> 
</div>
<script>
var app = angular.module('myApp', []);
//create a service mitsuplik
app.service('mitsuplik', function() {
    this.myFunc = function (parametro) {
        var tmp = ""; 
        for (var x=0;x<parametro.length;x++)
            {
            tmp = parametro.substring(x,x+1) + tmp;
            } 
        return tmp;
    }
});
//Calling our service
app.controller('myCtrl', function($scope, mitsuplik) { 
  $scope.chamar = function() { 
        $scope.resposta = mitsuplik.myFunc($scope.pergunta); 
    };
  //if mitsuplik press [ENTER], execute too
  $scope.pressionou_enter = function(keyEvent) {
             if (keyEvent.which === 13) 
                { 
                $scope.chamar();
                }

    }
});
</script>
</body>
</html>

2

Dies ist eine Erweiterung der Antwort von EpokK.

Ich hatte das gleiche Problem, eine Bereichsfunktion aufrufen zu müssen, wenn die Eingabetaste in einem Eingabefeld gedrückt wird. Ich wollte aber auch den Wert des Eingabefeldes an die angegebene Funktion übergeben. Das ist meine Lösung:

app.directive('ltaEnter', function () {
return function (scope, element, attrs) {
    element.bind("keydown keypress", function (event) {
        if(event.which === 13) {
          // Create closure with proper command
          var fn = function(command) {
            var cmd = command;
            return function() {
              scope.$eval(cmd);
            };
          }(attrs.ltaEnter.replace('()', '("'+ event.target.value +'")' ));

          // Apply function
          scope.$apply(fn);

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

});

Die Verwendung in HTML ist wie folgt:

<input type="text" name="itemname" lta-enter="add()" placeholder="Add item"/>

Ein großes Lob an EpokK für seine Antwort.


<input type="text" name="itemname" ng-model="item.itemname" lta-enter="add(item.itemname)" placeholder="Add item"/>
Aycanadal

1

Was ist damit?:

<form ng-submit="chat.sendMessage()">
    <input type="text" />
    <button type="submit">
</form>

Wenn Sie nun die Eingabetaste drücken, nachdem Sie etwas in Ihre Eingabe geschrieben haben, weiß das Formular, wie es damit umgeht.


Wie / wo ist chat.sendMessage()definiert
Aaron McMillin

0

Ein Beispiel für Code, den ich für mein Projekt gemacht habe. Grundsätzlich fügen Sie Ihrer Entität Tags hinzu. Stellen Sie sich vor, Sie haben Eingabetext. Bei der Eingabe des Tag-Namens erhalten Sie ein Dropdown-Menü mit vorinstallierten Tags zur Auswahl. Sie navigieren mit Pfeilen und wählen mit Enter:

HTML + AngularJS v1.2.0-rc.3

    <div>
        <form ng-submit="addTag(newTag)">
            <input id="newTag" ng-model="newTag" type="text" class="form-control" placeholder="Enter new tag"
                   style="padding-left: 10px; width: 700px; height: 33px; margin-top: 10px; margin-bottom: 3px;" autofocus
                   data-toggle="dropdown"
                   ng-change="preloadTags()"
                   ng-keydown="navigateTags($event)">
            <div ng-show="preloadedTags.length > 0">
                <nav class="dropdown">
                    <div class="dropdown-menu preloadedTagPanel">
                        <div ng-repeat="preloadedTag in preloadedTags"
                             class="preloadedTagItemPanel"
                             ng-class="preloadedTag.activeTag ? 'preloadedTagItemPanelActive' : '' "
                             ng-click="selectTag(preloadedTag)"
                             tabindex="{{ $index }}">
                            <a class="preloadedTagItem"
                               ng-class="preloadedTag.activeTag ? 'preloadedTagItemActive' : '' "
                               ng-click="selectTag(preloadedTag)">{{ preloadedTag.label }}</a>
                        </div>
                    </div>
                </nav>
            </div>
        </form>
    </div>

Controller.js

$scope.preloadTags = function () {
    var newTag = $scope.newTag;
    if (newTag && newTag.trim()) {
        newTag = newTag.trim().toLowerCase();

        $http(
            {
                method: 'GET',
                url: 'api/tag/gettags',
                dataType: 'json',
                contentType: 'application/json',
                mimeType: 'application/json',
                params: {'term': newTag}
            }
        )
            .success(function (result) {
                $scope.preloadedTags = result;
                $scope.preloadedTagsIndex = -1;
            }
        )
            .error(function (data, status, headers, config) {
            }
        );
    } else {
        $scope.preloadedTags = {};
        $scope.preloadedTagsIndex = -1;
    }
};

function checkIndex(index) {
    if (index > $scope.preloadedTags.length - 1) {
        return 0;
    }
    if (index < 0) {
        return $scope.preloadedTags.length - 1;
    }
    return index;
}

function removeAllActiveTags() {
    for (var x = 0; x < $scope.preloadedTags.length; x++) {
        if ($scope.preloadedTags[x].activeTag) {
            $scope.preloadedTags[x].activeTag = false;
        }
    }
}

$scope.navigateTags = function ($event) {
    if (!$scope.newTag || $scope.preloadedTags.length == 0) {
        return;
    }
    if ($event.keyCode == 40) {  // down
        removeAllActiveTags();
        $scope.preloadedTagsIndex = checkIndex($scope.preloadedTagsIndex + 1);
        $scope.preloadedTags[$scope.preloadedTagsIndex].activeTag = true;
    } else if ($event.keyCode == 38) {  // up
        removeAllActiveTags();
        $scope.preloadedTagsIndex = checkIndex($scope.preloadedTagsIndex - 1);
        $scope.preloadedTags[$scope.preloadedTagsIndex].activeTag = true;
    } else if ($event.keyCode == 13) {  // enter
        removeAllActiveTags();
        $scope.selectTag($scope.preloadedTags[$scope.preloadedTagsIndex]);
    }
};

$scope.selectTag = function (preloadedTag) {
    $scope.addTag(preloadedTag.label);
};

CSS + Bootstrap v2.3.2

.preloadedTagPanel {
    background-color: #FFFFFF;
    display: block;
    min-width: 250px;
    max-width: 700px;
    border: 1px solid #666666;
    padding-top: 0;
    border-radius: 0;
}

.preloadedTagItemPanel {
    background-color: #FFFFFF;
    border-bottom: 1px solid #666666;
    cursor: pointer;
}

.preloadedTagItemPanel:hover {
    background-color: #666666;
}

.preloadedTagItemPanelActive {
    background-color: #666666;
}

.preloadedTagItem {
    display: inline-block;
    text-decoration: none;
    margin-left: 5px;
    margin-right: 5px;
    padding-top: 5px;
    padding-bottom: 5px;
    padding-left: 20px;
    padding-right: 10px;
    color: #666666 !important;
    font-size: 11px;
}

.preloadedTagItem:hover {
    background-color: #666666;
}

.preloadedTagItemActive {
    background-color: #666666;
    color: #FFFFFF !important;
}

.dropdown .preloadedTagItemPanel:last-child {
    border-bottom: 0;
}

2
Ich denke, das ist eine böse Lösung. Ein Controller sollte nicht mit UI-Dingen wie Tastendrücken umgehen.
Maya Kathrine Andersen

5
Diese Antwort enthält sozusagen viel "Rauschen", viel Markup, das sich - soweit ich auf einen Blick sehen kann - nicht auf die eigentliche Frage bezieht. Es könnte prägnanter / nützlicher sein, den Code in der Antwort zu verdichten und das vollständige Beispiel in einem Gist / jsfiddle / plnkr bereitzustellen.
Cornelius

1
@MartinAndersen, wo soll ein Tastendruck in einer eckigen App gehandhabt werden?
Emanegux

1
Wenn ich es mir jetzt ansehe, sieht es okay aus. Es ist im Grunde so, wie Tastendrücke immer mit dem JS-Ereignismodell behandelt wurden.
Maya Kathrine Andersen

0

Ich bin ein bisschen spät dran .. aber ich habe eine einfachere Lösung gefunden mit auto-focus.. Dies könnte für Schaltflächen oder andere nützlich sein, wenn ich ein dialog:

<button auto-focus ng-click="func()">ok</button>

Das sollte in Ordnung sein, wenn Sie die Taste Leertaste onoder Eingabetaste drücken möchten .


Bei der Frage geht es darum, die Eingabetaste zu drücken und etwas zu tun.
BlaShadow

0

Hier ist meine Anweisung:

mainApp.directive('number', function () {
    return {
        link: function (scope, el, attr) {
            el.bind("keydown keypress", function (event) {
                //ignore all characters that are not numbers, except backspace, delete, left arrow and right arrow
                if ((event.keyCode < 48 || event.keyCode > 57) && event.keyCode != 8 && event.keyCode != 46 && event.keyCode != 37 && event.keyCode != 39) {
                    event.preventDefault();
                }
            });
        }
    };
});

Verwendungszweck:

<input number />

0

Sie können ng-keydown, ng-keyup und ng-press wie diesen verwenden.

eine Funktion auslösen:

   <input type="text" ng-keypress="function()"/>

oder wenn Sie eine Bedingung haben, z. B. wenn er Escape drückt (27 ist der Schlüsselcode für Escape)

 <form ng-keydown=" event.which=== 27?cancelSplit():0">
....
</form>

0

Ich denke, die Verwendung von document.bind ist etwas eleganter

constructor($scope, $document) {
  var that = this;
  $document.bind("keydown", function(event) {
    $scope.$apply(function(){
      that.handleKeyDown(event);
    });
  });
}

So erhalten Sie ein Dokument zum Controller-Konstruktor:

controller: ['$scope', '$document', MyCtrl]

0
(function(angular) {
  'use strict';
angular.module('dragModule', [])
  .directive('myDraggable', ['$document', function($document) {
    return {
      link: function(scope, element, attr) {
         element.bind("keydown keypress", function (event) {
           console.log('keydown keypress', event.which);
            if(event.which === 13) {
                event.preventDefault();
            }
        });
      }
    };
  }]);
})(window.angular);

0

Alles, was Sie tun müssen, um die Veranstaltung zu erhalten, ist Folgendes:

console.log(angular.element(event.which));

Eine Direktive kann es tun, aber so machen Sie es nicht.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.