Jak użyć zdarzenia naciśnięcia klawisza w AngularJS?

410

Chcę złapać zdarzenie naciśnij klawisz Enter w polu tekstowym poniżej. Aby to wyjaśnić, używam a, ng-repeataby wypełnić całe ciało. Oto 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>

To jest mój moduł:

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

Używam zasobu do zapełnienia tabeli, a mój kod kontrolera to:

function Ajaxy($scope, $resource) {
//controller which has resource to populate the table 
}
Venkata Tata
źródło
1
Czy dane wejściowe znajdują się w formularzu?
callmekatootie
1
nie .. jest w stole !!
Venkata Tata

Odpowiedzi:

808

Musisz dodać 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>
EpokK
źródło
7
@DerekAdair Dyrektywa wiąże się keydowni keypressimprez elementu jest przypisany. Po odebraniu zdarzenia dostarczone wyrażenie jest oceniane w $applybloku.
Pete Martin,
7
Bezpieczniej zdefiniować klucz w ten sposób: var key = typeof event.which === "undefined" ? event.keyCode : event.which;tak długo, jak zdarzenie. Które nie jest używane przez każdą przeglądarkę. Zobacz komentarze tutaj: stackoverflow.com/a/4471635/2547632
Gabriel
3
Dodałbym również keyupw teście wiązania
użytkownik1713964
59
zauważ także, że używanie przedrostka ng nie jest zalecane, ponieważ może to kolidować z przyszłymi dyrektywami ng- *. Zamiast tego użyj własnego
Marius Balčytis
3
Nie zapomnij zniszczyć swoich powiązań: scope. $
On
345

Alternatywą jest zastosowanie standardowej dyrektywy ng-keypress="myFunct($event)"

Następnie w kontrolerze możesz mieć:

...

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

...
Chris Reynolds
źródło
18
Aby zaoszczędzić innym ludziom trochę czasu, ng-keypressnie wydaje się być częścią angularui-keypress
1.0.x.
1
Myślę, że powyższy komentarz miał na celu inną odpowiedź. (Tylko w celach informacyjnych.)
Cornelius
Martin to właściwie funkcja kontrolera: do obsługi zdarzeń interfejsu użytkownika.
Trevor de Koekkoek
5
Jeszcze lepiej, użyj ngKeypress i przekaż zdarzenie $ do niestandardowego filtra.
Martin
7
Najlepsza odpowiedź +1. Dlaczego powinienem stworzyć własną dyrektywę, jeśli taka istnieje, już zawartą w Angular?
bFunc
179

Moje najprostsze podejście z wykorzystaniem tylko wbudowanej dyrektywy kątowej:

ng-keypress, ng-keydownLub ng-keyup.

Zwykle chcemy dodać obsługę klawiatury dla czegoś, co jest już obsługiwane przez kliknięcie ng.

na przykład:

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

Dodajmy teraz obsługę klawiatury.

wyzwalaj klawiszem Enter:

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

klawiszem spacji:

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

spacją lub wprowadź klucz:

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

jeśli jesteś w nowoczesnej przeglądarce

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

Więcej informacji o keyCode:
keyCode jest przestarzały, ale dobrze obsługiwany API, zamiast tego możesz użyć $ evevt.key w obsługiwanej przeglądarce.
Zobacz więcej w https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key

Eric Chen
źródło
1
sekret jest warunkiem wykonania metody $ event.which === 13 && action () - dzięki!
user12121234
1
„$ event.which” nie działa dla mnie, ale znalazłem „$ event.keyCode”, który działa.
Karl Adler,
event. który jest niezdefiniowany w IE <9 przy keydown i keyup.
Eric Chen
2
„stare przeglądarki jak IE9” .. nigdy nie myślałem, że ten dzień nadejdzie :)
Mihnea Belcin
1
Dlaczego nikt tutaj nie zaktualizował fragmentów kodu, aby użyć $ event.keyCode? Zrobiłbym to sam, ale z jakiegoś powodu nie mogę.
Nathan Hazzard
102

Kolejna prosta alternatywa:

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

I alternatywa ng-ui:

<input ng-model="edItem" type="text" ui-keypress="{'enter':'foo(edItem)'}"/>
Rodolfo Jorge Nemer Nogueira
źródło
9
ng-ui to niejednoznaczne, zamiast tego powinieneś powiedzieć „UI.Utils” lub udostępnić link: angular-ui.github.io/ui-utils
Paulo Oliveira
ui-utils wydaje się być przestarzałe
cafesanu
19

Oto, co wymyśliłem, gdy tworzyłem aplikację o podobnych wymaganiach, nie wymaga pisania dyrektywy i stosunkowo łatwo jest powiedzieć, co robi:

<input type="text" ng-keypress="($event.charCode==13)?myFunction():return" placeholder="Will Submit on Enter">
marcinzajkowski
źródło
3
Prosty i skuteczny.
Xplouder,
15

Możesz użyć ng-keydown = "myFunction ($ event)" jako atrybutu.

<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 :)
    }
}
Fineas
źródło
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');
    }
};
Jose Durley Lancheros
źródło
3

Możesz także zastosować go do kontrolera na elemencie nadrzędnym. Ten przykład można wykorzystać do podświetlenia wiersza w tabeli za pomocą klawiszy strzałek w górę / w dół.

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>

będzie Farrell
źródło
3

Próbować

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

nic dla mnie nie zrobił

Strangley przykład na https://docs.angularjs.org/api/ng/directive/ngKeypress , który robi ng-keypress = "count = count + 1", działa.

Znalazłem alternatywne rozwiązanie, w którym naciśnięcie Enter wywołuje kliknięcie przycisku ng.

<input ng-model="..." onkeypress="if (event.which==13) document.getElementById('button').click()"/>
<button id="button" ng-click="doSomething()">Done</button>
Snaran
źródło
ng-keypress="console.log('foo')"też nie działało dla mnie, ale jeśli to zrobisz, to ng-keypress="fooMethod()"w twoim kontrolerze $scope.fooMethod = function() { console.log('fooMethod called'); }działa.
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>
Marcus Poli
źródło
2

To jest rozszerzenie odpowiedzi EpokK.

Miałem ten sam problem z koniecznością wywołania funkcji zasięgu, gdy klawisz Enter jest wprowadzany do pola wprowadzania. Jednak chciałem również przekazać wartość pola wejściowego do określonej funkcji. To jest moje rozwiązanie:

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();
        }
    });
};

});

Zastosowanie w HTML jest następujące:

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

Uznanie dla EpokK za jego odpowiedź.

tassaert.l
źródło
<input type="text" name="itemname" ng-model="item.itemname" lta-enter="add(item.itemname)" placeholder="Add item"/>
aycanadal
1

A co z tym?:

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

Teraz, kiedy naciśniesz klawisz Enter po napisaniu czegoś w danych wejściowych, formularz wie, jak sobie z tym poradzić.

juanmorschrott
źródło
Jak / gdzie chat.sendMessage()zdefiniowano
Aaron McMillin
0

Oto przykład kodu, który zrobiłem dla mojego projektu. Zasadniczo dodajesz tagi do swojego bytu. Wyobraź sobie, że masz wprowadzony tekst. Po wprowadzeniu nazwy znacznika pojawia się menu rozwijane ze wstępnie załadowanymi znacznikami do wyboru, nawigujesz za pomocą strzałek i wybierasz za pomocą 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;
}
Dmitri Algazin
źródło
2
Myślę, że to paskudne rozwiązanie. Kontroler nie powinien obsługiwać takich elementów interfejsu użytkownika, jak naciśnięcia klawiszy.
Maya Kathrine Andersen
5
Ta odpowiedź zawiera wiele „szumów”, w pewnym sensie, zawiera znaczniki, które - o ile widzę na pierwszy rzut oka - nie odnoszą się do aktualnego pytania. Bardziej zwięzłe / użyteczne może być skondensowanie kodu w odpowiedzi i podanie pełnego przykładu w gist / jsfiddle / plnkr.
Cornelius
1
@MartinAndersen, gdzie należy obsługiwać naciśnięcie klawisza w aplikacji kątowej?
Emanegux,
1
Kiedy patrzę na to teraz, wygląda dobrze. Zasadniczo to, w jaki sposób naciśnięcia klawiszy były zawsze obsługiwane w modelu zdarzeń JS.
Maya Kathrine Andersen
0

Jestem trochę spóźniony .. ale znalazłem prostsze rozwiązanie, używając auto-focus... Może to być przydatne dla przycisków lub innych, gdy pop dialog:

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

To powinno być w porządku, jeśli chcesz nacisnąć przycisk onSpacja lub Enter.

Abdellah Alaoui
źródło
pytanie dotyczy prasy enter i zrób coś.
BlaShadow,
0

oto moja dyrektywa:

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();
                }
            });
        }
    };
});

stosowanie:

<input number />
WtFudgE
źródło
0

możesz użyć ng-keydown, ng-keyup, ng-press, takich jak to.

aby uruchomić funkcję:

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

lub jeśli masz jeden warunek, na przykład kiedy naciska klawisz Escape (27 to kod klucza do ucieczki)

 <form ng-keydown=" event.which=== 27?cancelSplit():0">
....
</form>
Eassa Nassar
źródło
0

Myślę, że używanie document.bind jest nieco bardziej eleganckie

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

Aby pobrać dokument do konstruktora kontrolera:

controller: ['$scope', '$document', MyCtrl]
FreshPow
źródło
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);
Mukundhan
źródło
0

Wszystko, co musisz zrobić, aby uzyskać wydarzenie, to:

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

Dyrektywa może to zrobić, ale nie tak to robisz.

Konkret
źródło