Come usare un evento keypress in AngularJS?


410

Voglio catturare l'evento premere il tasto Invio nella casella di testo qui sotto. Per rendere più chiaro sto usando a ng-repeatper popolare il corpo. Ecco l'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>

Questo è il mio modulo:

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

Sto usando una risorsa per popolare la tabella e il mio codice controller è:

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

1
L'input è all'interno di un modulo?
callmekatootie,

1
no .. è in un tavolo !!
Venkata Tata,

Risposte:


808

Devi aggiungere un directive, in questo modo:

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 La direttiva si lega agli eventi keydowne keypressall'elemento a cui è attribuita. Quando viene ricevuto l'evento, l'espressione fornita viene valutata all'interno di un $applyblocco.
Pete Martin,

7
Più sicuro definire la chiave in questo modo: var key = typeof event.which === "undefined" ? event.keyCode : event.which;purché event.che non venga utilizzato da tutti i browser. Vedi i commenti qui: stackoverflow.com/a/4471635/2547632
Gabriel,

3
Vorrei aggiungere anche keyupnel test di
associazione

59
si noti inoltre che non è consigliabile utilizzare il prefisso ng, poiché ciò potrebbe scontrarsi con le future direttive ng- *. Usa invece il tuo
Marius Balčytis

3
Non dimenticare di distruggere i tuoi binding: scope. $ On ('$ destroy', function () {element.unbind ('keydown');})
nawlbergs,

345

Un'alternativa è usare la direttiva standard ng-keypress="myFunct($event)"

Quindi nel tuo controller puoi avere:

...

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

...

18
Per salvare altre persone un po 'di tempo, ng-keypressnon sembra far parte dell'angolare 1.0.x, ui-keypress(con semantica di chiamata leggermente diversa) è disponibile però: angular-ui.github.io/ui-utils
Cebjyre

1
Penso che il commento sopra sia stato rivolto a una risposta diversa. (Solo per riferimento.)
Cornelius,

Martin è in realtà la funzione di un controller: gestire gli eventi dell'interfaccia utente.
Trevor de Koekkoek,

5
Meglio ancora, usa ngKeypress e passa l'evento $ a un filtro personalizzato.
Martin,

7
Migliore risposta +1. Perché dovrei fare la mia direttiva, se ce n'è una, già inclusa in Angular?
bFunc

179

Il mio approccio più semplice usando solo la direttiva angolare incorporata:

ng-keypress, ng-keydownong-keyup .

Di solito, vogliamo aggiungere il supporto della tastiera per qualcosa che è già stato gestito da ng-click.

per esempio:

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

Ora aggiungiamo il supporto per la tastiera.

trigger tramite tasto invio:

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

con il tasto spazio:

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

dallo spazio o tasto invio:

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

se sei nel browser moderno

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

Ulteriori informazioni su keyCode:
keyCode è deprecato ma API ben supportata, puoi invece utilizzare $ evevt.key nel browser supportato.
Scopri di più su https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key


1
il segreto è il condizionale prima del metodo da eseguire $ event.which === 13 && action () - grazie!
user12121234

1
'$ event.which' non funziona per me, ma ho trovato '$ event.keyCode' che funziona.
Karl Adler,

event.che non definito in IE <9 su keydown e keyup.
Eric Chen,

2
"vecchi browser come IE9" .. mai pensato che questo giorno arriverà :)
Mihnea Belcin

1
Perché nessuno ha aggiornato qui i frammenti di codice per usare $ event.keyCode? Lo modificherei da solo, ma non posso farlo per qualche motivo.
Nathan Hazzard,


19

Ecco cosa ho capito quando stavo costruendo un'app con un requisito simile, non richiede la scrittura di una direttiva ed è relativamente semplice dire cosa fa:

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

3
Semplice ed efficace
Xplouder,

15

È possibile utilizzare ng-keydown = "myFunction ($ event)" come attributo.

<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

Puoi anche applicarlo a un controller su un elemento padre. Questo esempio può essere utilizzato per evidenziare una riga in una tabella premendo i tasti freccia su / giù.

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

Provando

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

non ha fatto niente per me.

Stranamente l'esempio su https://docs.angularjs.org/api/ng/directive/ngKeypress , che fa ng-keypress = "count = count + 1", funziona.

Ho trovato una soluzione alternativa, che premendo Invio invoca il pulsante ng-clic del pulsante.

<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')"non ha funzionato neanche per me, ma se lo fai ng-keypress="fooMethod()"e nel tuo controller $scope.fooMethod = function() { console.log('fooMethod called'); }funziona.
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

Questa è un'estensione sulla risposta di EpokK.

Ho avuto lo stesso problema di dover chiamare una funzione scope quando invio viene premuto su un campo di input. Tuttavia, volevo anche passare il valore del campo di input alla funzione specificata. Questa è la mia soluzione:

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

});

L'uso in HTML è il seguente:

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

Complimenti a EpokK per la sua risposta.


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

1

Che dire di questo?:

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

Ora quando premi il tasto Invio dopo aver scritto qualcosa nel tuo input, il modulo sa come gestirlo.


Come / dove viene chat.sendMessage()definito
Aaron McMillin

0

Qualche esempio di codice che ho fatto per il mio progetto. Fondamentalmente aggiungi tag alla tua entità. Immagina di avere un testo di input, inserendo il nome del tag si ottiene un menu a discesa con tag precaricati tra cui scegliere, si naviga con le frecce e si seleziona con Invio:

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
Penso che questa sia una brutta soluzione. Un controller non dovrebbe gestire elementi dell'interfaccia utente come i tasti premuti.
Maya Kathrine Andersen,

5
Questa risposta contiene molto "rumore", per così dire, contenente un sacco di markup che, per quanto posso vedere a colpo d'occhio, non riguarda la domanda attuale. Potrebbe essere più conciso / utile condensare il codice nella risposta e fornire l'esempio completo in gist / jsfiddle / plnkr.
Cornelius,

1
@MartinAndersen, dove dovrebbe essere gestito un tasto premuto in un'app angolare?
Emanegux,

1
Quando lo guardo ora sembra a posto. Fondamentalmente è come i tasti premuti sono sempre stati gestiti con il modello di eventi JS.
Maya Kathrine Andersen,

0

Sono un po 'in ritardo .. ma ho trovato una soluzione più semplice usando auto-focus.. Questo potrebbe essere utile per i pulsanti o altro quando si fa scoppiare un dialog:

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

Questo dovrebbe andare bene se si desidera premere il pulsante onSpazio o Invio clic.


la domanda riguarda premere Invio e fare qualcosa.
BlaShadow,

0

ecco la mia direttiva:

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

utilizzo:

<input number />

0

puoi usare ng-keydown, ng-keyup, ng-press come questo.

trigerare una funzione:

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

o se hai una condizione come quando preme escape (27 è il codice chiave per la fuga)

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

0

Penso che usare document.bind sia un po 'più elegante

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

Per ottenere il documento per il costruttore del controller:

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

Tutto quello che devi fare per ottenere l'evento è il seguente:

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

Una direttiva può farlo, ma non è così che lo fai.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.