Bagaimana cara menggunakan acara penekanan tombol di AngularJS?


410

Saya ingin menangkap acara tekan tombol enter pada kotak teks di bawah ini. Untuk membuatnya lebih jelas, saya menggunakan a ng-repeatuntuk mengisi tbody. Ini HTML-nya:

<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>

Ini adalah modul saya:

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

Saya menggunakan sumber daya untuk mengisi tabel dan kode pengontrol saya adalah:

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

1
Apakah input di dalam formulir?
callmekatootie

1
tidak .. ada di meja !!
Venkata Tata

Jawaban:


808

Anda perlu menambahkan directive, seperti ini:

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 Arahan mengikat ke keydowndan keypressperistiwa dari elemen yang dikaitkan dengannya. Ketika acara diterima, ekspresi yang disediakan dievaluasi di dalam $applyblok.
Pete Martin

7
Lebih aman untuk mendefinisikan kunci seperti ini: var key = typeof event.which === "undefined" ? event.keyCode : event.which;selama event.which tidak digunakan oleh setiap browser. Lihat komentar di sini: stackoverflow.com/a/4471635/2547632
Gabriel

3
Saya akan menambahkan juga keyupdalam tes mengikat
user1713964

59
juga perhatikan bahwa menggunakan awalan ng tidak disarankan, karena ini dapat berbenturan dengan arahan ng * di masa mendatang. Gunakan milik Anda sendiri
Marius Balčytis

3
Jangan lupa untuk menghancurkan binding Anda: scope. $ On ('$ destroy', function () {element.unbind ('keydown');})
nawlbergs

345

Alternatifnya adalah menggunakan arahan standar ng-keypress="myFunct($event)"

Kemudian di controller Anda, Anda dapat memiliki:

...

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

...

18
Untuk menghemat waktu orang lain, ng-keypresstampaknya tidak menjadi bagian dari sudut 1.0.x, ui-keypress(dengan semantik panggilan yang sedikit berbeda) tersedia: angular-ui.github.io/ui-utils
Cebjyre

1
Saya pikir komentar di atas ditujukan untuk jawaban yang berbeda. (Hanya untuk referensi.)
Cornelius

Martin itu sebenarnya fungsi pengontrol: untuk menangani acara UI.
Trevor de Koekkoek

5
Lebih baik lagi, gunakan ngKeypress dan kirimkan $ event ke filter khusus.
Martin

7
Jawaban terbaik +1. Mengapa saya harus membuat arahan saya sendiri, jika ada, sudah termasuk dalam Angular?
bFunc

179

Pendekatan saya yang paling sederhana menggunakan arahan built-in hanya sudut:

ng-keypress, ng-keydownatau ng-keyup.

Biasanya, kami ingin menambahkan dukungan keyboard untuk sesuatu yang sudah ditangani oleh ng-klik.

contohnya:

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

Sekarang, mari kita tambahkan dukungan keyboard.

pemicu dengan memasukkan kunci:

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

dengan tombol spasi:

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

dengan spasi atau masukkan kunci:

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

jika Anda menggunakan browser modern

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

Lebih lanjut tentang keyCode:
keyCode sudah usang tetapi didukung API, Anda bisa menggunakan $ evevt.key sebagai gantinya di browser yang didukung.
Lihat lebih banyak di https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key


1
rahasianya adalah syarat sebelum metode yang akan dieksekusi $ event.which === 13 && action () - terima kasih!
user12121234

1
'$ event.which' tidak berfungsi untuk saya, tetapi saya menemukan '$ event.keyCode' yang berfungsi.
Karl Adler

event.yang tidak didefinisikan dalam IE <9 pada keydown dan keyup.
Eric Chen

2
"browser lama seperti IE9" .. tidak pernah mengira hari ini akan datang :)
Mihnea Belcin

1
Mengapa tidak ada orang yang memperbarui cuplikan kode di sini untuk menggunakan $ event.keyCode? Saya akan mengeditnya sendiri, tetapi saya tidak dapat karena suatu alasan.
Nathan Hazzard


19

Inilah yang saya ketahui ketika saya sedang membangun sebuah aplikasi dengan persyaratan yang sama, tidak perlu menulis arahan dan relatif mudah untuk mengetahui apa yang dilakukannya:

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

3
Sederhana dan efektif.
Xplouder

15

Anda dapat menggunakan ng-keydown = "myFunction ($ event)" sebagai atribut.

<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

Anda juga dapat menerapkannya pada pengontrol pada elemen induk. Contoh ini dapat digunakan untuk menyorot baris dalam sebuah tabel dengan menekan tombol panah atas / bawah.

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

Mencoba

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

tidak melakukan apa pun untuk saya.

Strangley sampel di https://docs.angularjs.org/api/ng/directive/ngKeypress , yang berfungsi ng-keypress = "count = count +1", berfungsi.

Saya menemukan solusi alternatif, yang telah menekan Enter untuk memanggil tombol ng-klik.

<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')"tidak bekerja untuk saya juga, tetapi jika Anda melakukannya ng-keypress="fooMethod()"dan di controller Anda $scope.fooMethod = function() { console.log('fooMethod called'); }tidak berfungsi.
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

Ini adalah ekstensi dari jawaban dari EpokK.

Saya memiliki masalah yang sama karena harus memanggil fungsi lingkup ketika enter didorong pada bidang input. Namun saya juga ingin meneruskan nilai bidang input ke fungsi yang ditentukan. Ini solusi saya:

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

});

Penggunaan dalam HTML adalah sebagai berikut:

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

Kudos to EpokK untuk jawabannya.


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

1

Bagaimana dengan ini?:

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

Sekarang ketika Anda menekan tombol enter setelah menulis sesuatu di input Anda, formulir tahu bagaimana menanganinya.


Bagaimana / di mana chat.sendMessage()didefinisikan
Aaron McMillin

0

Beberapa contoh kode yang saya lakukan untuk proyek saya. Pada dasarnya Anda menambahkan tag ke entitas Anda. Bayangkan Anda memiliki input teks, pada memasukkan nama Tag Anda mendapatkan menu drop-down dengan tag yang telah dimuat untuk dipilih, Anda menavigasi dengan panah dan pilih dengan 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
Saya pikir ini adalah solusi yang buruk. Pengontrol seharusnya tidak menangani hal-hal UI seperti penekanan tombol.
Maya Kathrine Andersen

5
Jawaban ini mengandung banyak "noise", dalam cara berbicara, mengandung banyak markup yang tidak - sejauh yang saya bisa lihat sekilas - tidak berhubungan dengan pertanyaan aktual yang ada. Mungkin lebih ringkas / berguna untuk menyingkat kode dalam jawaban dan memberikan contoh lengkap di intisari / jsfiddle / plnkr.
Cornelius

1
@ MartinAndersen, di mana penekanan tombol harus ditangani di aplikasi sudut?
Emanegux

1
Ketika saya melihatnya sekarang terlihat baik-baik saja. Ini pada dasarnya bagaimana penekanan tombol selalu ditangani dengan model acara JS.
Maya Kathrine Andersen

0

Saya agak terlambat .. tetapi saya menemukan solusi yang lebih sederhana menggunakan auto-focus.. Ini bisa berguna untuk tombol atau lainnya ketika muncul dialog:

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

Itu akan baik-baik saja jika Anda ingin menekan tombol onSpasi atau Masukkan klik.


pertanyaannya adalah tentang tekan enter dan lakukan sesuatu.
BlaShadow

0

inilah arahan saya:

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

pemakaian:

<input number />

0

Anda dapat menggunakan ng-keydown, ng-keyup, ng-tekan seperti ini.

untuk mengaktifkan fungsi:

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

atau jika Anda memiliki satu kondisi seperti ketika dia menekan escape (27 adalah kode kunci untuk escape)

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

0

Saya pikir menggunakan document.bind sedikit lebih elegan

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

Untuk mendapatkan dokumen ke konstruktor pengontrol:

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

Yang perlu Anda lakukan untuk mendapatkan acara adalah sebagai berikut:

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

Arahan dapat melakukannya, tetapi bukan itu yang Anda lakukan.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.