AngularJS'de bir tuşa basma olayı nasıl kullanılır?


410

Aşağıdaki metin kutusunda enter tuşuna basın olayını yakalamak istiyorum. Daha açık bir şekilde ifade ng-repeatetmek için tbody'i doldurmak için bir kullanıyorum . İşte 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>

Bu benim modülüm:

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

Tablo doldurmak için bir kaynak kullanıyorum ve denetleyici kodum:

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

1
Girdi bir formun içinde mi?
callmekatootie

1
hayır .. onun bir tablo !!
Venkata Tata

Yanıtlar:


808

Aşağıdaki directivegibi bir eklemeniz gerekir :

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 Yönerge , atfedildiği öğeye keydownve keypressolaylara bağlanır . Olay alındığında, sağlanan ifade bir $applyblok içinde değerlendirilir .
Pete Martin

7
Anahtarı şu şekilde tanımlamak daha güvenlidir: var key = typeof event.which === "undefined" ? event.keyCode : event.which;her tarayıcı tarafından kullanılmayan event. sürece. Buradaki yorumlara bakın: stackoverflow.com/a/4471635/2547632
Gabriel

3
Ben de eklersiniz keyupbağlama testi içinde
user1713964

59
ayrıca ng önekinin kullanılması önerilmemektedir, çünkü bu, gelecekteki ng- * yönergelerine aykırı olabilir.
Onun

3
Bağlamalarınızı yok etmeyi unutmayın: kapsam. $ On ('$ destroy', function () {element.unbind ('keydown');})
nawlbergs

345

Alternatif olarak standart yönerge kullanmak ng-keypress="myFunct($event)"

Ardından kontrol cihazınızda şunları yapabilirsiniz:

...

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

...

18
Diğer insanlara biraz zaman kazanmak için, ng-keypressaçısal 1.0.x parçası olmak görünmüyor ui-keypress(biraz farklı arama semantik ile) olsa mevcuttur: angular-ui.github.io/ui-utils
Cebjyre

1
Bunun üstündeki yorumun farklı bir cevaba yönelik olduğunu düşünüyorum. (Sadece referans içindir.)
Cornelius

Martin aslında bir denetleyicinin işlevi: UI olaylarını işlemek için.
Trevor de Koekkoek

5
Daha da iyisi, ngKeypress kullanın ve $ olayını özel bir filtreye geçirin.
Martin

7
En iyi cevap +1. Açılıma zaten dahil edilmişse neden kendi direktifimi yapmalıyım?
bFunc

179

Sadece açısal yerleşik yönergeyi kullanarak en basit yaklaşımım:

ng-keypress, ng-keydownveya ng-keyup.

Genellikle, ng-click ile zaten ele alınan bir şey için klavye desteği eklemek istiyoruz.

Örneğin:

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

Şimdi klavye desteği ekleyelim.

Enter tuşuyla tetikle:

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

boşluk tuşu ile:

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

boşlukla veya enter tuşuna basarak:

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

eğer modern tarayıcıda iseniz

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


KeyCode hakkında daha fazla bilgi: keyCode kullanımdan kaldırıldı, ancak iyi desteklenen bir API, bunun yerine desteklenen tarayıcıda $ evevt.key kullanabilirsiniz. Https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key adresinde
daha fazlasını görün


1
sırrı yürütülecek yöntem önce koşullu $ event.which === 13 && action () - teşekkürler!
user12121234

1
'$ event.which' benim için çalışmıyor, ancak çalışan '$ event.keyCode'u buldum.
Karl Adler

event.which, IE <9'da tuş kilidi ve tuş üzerinde tanımlanmamıştır.
Eric Chen

2
"IE9 gibi eski tarayıcılar" .. bu günün geleceğini hiç düşünmedim :)
Mihnea Belcin

1
Neden kimse kod snippet'lerini $ event.keyCode kullanacak şekilde güncellemedi? Kendim düzenlerdim, ama bir nedenden dolayı yapamıyorum.
Nathan Hazzard

102

Başka bir basit alternatif:

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

Ve ng-ui alternatifi:

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

9
ng-ui belirsiz, bunun yerine "UI.Utils" demelisiniz veya bağlantıyı paylaşmalısınız: angular-ui.github.io/ui-utils
Paulo Oliveira

ui-utils kullanımdan kaldırılmış gibi görünüyor
cafesanu

19

İşte benzer bir gereksinime sahip bir uygulama oluştururken anladım, bir yönerge yazmayı gerektirmiyor ve ne yaptığını söylemek nispeten basit:

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

3
Basit ve etkili.
Xplouder

15

Sen kullanabilirsiniz -keydown ng = "myFunction ($ event)" özelliği olarak.

<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

Üst öğedeki bir denetleyiciye de uygulayabilirsiniz. Bu örnek, yukarı / aşağı ok tuşlarına basarak tablodaki bir satırı vurgulamak için kullanılabilir.

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

çalışılıyor

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

benim için hiçbir şey yapmadı.

Örneği https://docs.angularjs.org/api/ng/directive/ng adresinde Strangley ng-keypress = "count = count + 1" yapan çalışır.

Enter tuşuna basarak alternatif bir çözüm buldum, düğmenin ng-click'i çağırdı.

<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')"benim için de işe yaramadı, ama eğer yaparsanız ng-keypress="fooMethod()"ve kontrol cihazınızda $scope.fooMethod = function() { console.log('fooMethod called'); }çalışırsa.
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

Bu, EpokK tarafından verilen yanıtın bir uzantısıdır.

Ben bir girdi alanına girdi itildiğinde bir kapsam işlevi çağırmak zorunda aynı sorun vardı. Ancak girdi alanının değerini belirtilen işleve de aktarmak istedim . Bu benim çözümüm:

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

});

HTML'de kullanım aşağıdaki gibidir:

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

Cevabı EpokK'a cevabı için.


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

1

Peki buna ne dersin?:

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

Şimdi girdinize bir şey yazdıktan sonra enter tuşuna bastığınızda, form onu ​​nasıl kullanacağınızı bilir.


Nasıl / nerede chat.sendMessage()tanımlanır
Aaron McMillin

0

Projem için yaptığım bazı kod örnekleri. Temel olarak öğenize etiketler eklersiniz. Girdi metniniz olduğunu düşünün, önceden yüklenmiş etiketlerin bulunduğu açılır menüden aldığınız Etiket adını girdiğinizde oklarla geziniyor ve Enter ile seçiyorsunuz:

HTML + Açısal JS 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
Bence bu kötü bir çözüm. Bir denetleyici, tuşa basma gibi UI işlemlerini yapmamalıdır.
Maya Kathrine Andersen

5
Bu cevap, bir bakışta, bir bakışta görebildiğim kadarıyla, eldeki asıl soru ile ilgili olmayan çok fazla işaretleme içeren bir çok "gürültü" içeriyor. Yanıttaki kodu yoğunlaştırmak ve tam örneği bir gist / jsfiddle / plnkr biçiminde sağlamak daha özlü / yararlı olabilir.
Cornelius

1
@MartinAndersen, açısal bir uygulamada bir tuşa basma nerede ele alınmalıdır?
Emanegux

1
Şimdi baktığımda iyi görünüyor. Temelde JS olay modeli ile tuşlara her zaman nasıl bakılır.
Maya Kathrine Andersen

0

Biraz geç kaldım .. ama kullanarak daha basit bir çözüm buldum auto-focus.. Bu bir haşhaş düğmeler veya diğer için yararlı olabilir dialog:

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

onBoşluk veya Enter tuşlarına basmak istiyorsanız bu iyi olur .


soru girmek basın ve bir şey yapmak.
BlaShadow

0

İşte benim direktifim:

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

kullanımı:

<input number />

0

bunun gibi ng-keydown, ng-keyup, ng-press kullanabilirsiniz.

bir işlevi tetiklemek için:

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

veya escape tuşuna bastığında olduğu gibi bir durumunuz varsa (27, kaçış için anahtar koddur)

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

0

Bence document.bind kullanmak biraz daha zarif

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

Denetleyici yapıcısına belge almak için:

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

Etkinliği almak için tek yapmanız gereken:

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

Bir yönerge olabilir bunu, ama bu değil nasıl bunu.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.