Очистить текстовое поле ввода в Angular / AngularUI с помощью клавиши ESC

В нескольких местах моего приложения Angular мне нужно очистить ввод от пользователя с помощью клавиши ESC. Проблема в том, что я не знаю, как это сделать с полями ввода текста (textarea очищает OK). Смотрите эту скрипку:

демонстрация проблемы с помощью jsFiddle

Привязка:

<input ng-model="search.query" ui-keypress="{esc: 'keyCallback($event)'}" />

Обратный звонок я использую:

$scope.keyCallback = function($event) {
  $event.preventDefault();
  $scope.search.query = '';
}

Может ли кто-нибудь, пожалуйста, выяснить, что мне нужно сделать, чтобы очистить ввод текста с помощью клавиши ESC?

РЕШЕНИЕ: Согласно рекомендациям bmleite, вам следует слушать не «нажатие клавиши», а < strong> 'keydown' и 'keyup'. Проблема заключалась в том, что «keydown» не работает в Firefox, поэтому только «keyup» выполнял волшебный трюк с прослушиванием ESC. ;)

Рабочая скрипка: http://jsfiddle.net/aGpNf/190/

ОБНОВЛЕНИЕ РЕШЕНИЯ. В конце концов, мне пришлось прислушиваться к событиям keydown и keyup. Потому что в моем случае FF сбрасывает поле ввода при нажатии клавиши ESC до предыдущего состояния, поэтому моя модель испортилась. Таким образом, keyup очищает модель, а keydown проверяет, пуста ли модель, и выполняет соответствующие действия. Мне также нужно вручную расфокусировать ввод, чтобы текст не появлялся снова.: /


person Jan Peša    schedule 01.02.2013    source источник
comment
Вы можете объяснить, что вы имеете в виду под ОБНОВЛЕНИЕМ РЕШЕНИЯ? Похоже, вам поможет, если AngularUI обернет вашу клавиатуру в $scope.$apply()? Если это так, можете ли вы открыть вопрос? Мне также любопытно, что вы имеете в виду, говоря, что текст снова появляется? Кроме того, вы можете сделать следующее: ui-keydown="{ 'esc enter': 'keyCallback($event)' }" и любая клавиша вызовет событие.   -  person ProLoser    schedule 01.02.2013
comment
если кто-то приходит сюда и просто не может запустить esc в Chrome ... выключите плагин Vimium или другой.   -  person Skylar Saveland    schedule 23.04.2013
comment
Это больше не работает ни в Chrome, ни в Firefox. Я не тестировал в IE / Edge или Opera.   -  person Terra Ashley    schedule 01.07.2016
comment
stackoverflow.com/a/46863552/2074346 - Лучший ответ   -  person Kishore Sahasranaman    schedule 04.01.2021


Ответы (6)


Принятый ответ не работает в IE 10/11. Вот решение на основе другого вопроса, которое:

Директива

.directive('escKey', function () {
  return function (scope, element, attrs) {
    element.bind('keydown keypress', function (event) {
      if(event.which === 27) { // 27 = esc key
        scope.$apply(function (){
          scope.$eval(attrs.escKey);
        });

        event.preventDefault();
      }
    });
    scope.$on('$destroy', function() {
        element.unbind('keydown keypress')
    })
  };
})

HTML:

<input ... ng-model="filter.abc" esc-key="resetFilter()" >

Ctrl

$scope.resetFilter = function() {
  $scope.filter.abc = null;
};
person s.Daniel    schedule 20.11.2014
comment
eval - это зло, вы можете правильно привязать метод к директиве, используя &, подробнее здесь. - person icl7126; 07.11.2015
comment
Мне это так понравилось, что после того, как я использовал его на кучу вещей, я просто пошел дальше и сделал репо для него. github.com/deltreey/angular-esc-key Если вы предпочитаете, я передать его вам, но я с радостью сохраню его. - person deltree; 11.12.2015
comment
Не стесняйтесь, я не против. Когда у меня будет время, я также попробую улучшить решение предложением @ icl7126 и отправлю запрос на перенос. Также, если у вас есть улучшения, не стесняйтесь обновлять мой ответ. - person s.Daniel; 14.12.2015
comment
Как передать элемент контроллеру, например esc-key = resetFilter ($ event), чтобы в контроллере я мог получить объект $ event.currentTarget - person tuananh; 27.05.2017
comment
Принятый ответ работает Angular 1.7 в соответствии с связанной проблемой - person usr-local-ΕΨΗΕΛΩΝ; 12.10.2018
comment
FYI event. Которое устарело developer.mozilla.org/en -US / docs / Web / API / KeyboardEvent / который. Я использовал event.key === "Escape" - person LazioTibijczyk; 02.01.2020

Я решаю эту проблему так (Контроллер как синтаксис vm):

HTML

<input ... ng-model="vm.item" ng-keyup="vm.checkEvents($event)">

Контроллер

...
vm.checkEvents = function ($event) {
    if ($event.keyCode == 27) {
        vm.item = "";   
    }
}
person Bijan    schedule 24.03.2015

Слушайте события 'keydown' или 'keyup' вместо 'keypress':

<input ng-model="search.query" ui-keydown="{esc: 'keyCallback($event)'}" />
person bmleite    schedule 01.02.2013
comment
Спасибо, что указали мне правильный путь. Перед тем, как написать этот вопрос, я попробовал 'keydown', но он не работал в FF, поэтому я подумал, что это было бы неправильным решением. После вашего совета я также попробовал «keyup» и вуаля, это помогло (как в FF, так и в Chrome). - person Jan Peša; 01.02.2013
comment
Вы также можете просто сделать это в строке: ui-keydown="{esc: 'search.query=\"\"'}" - person ProLoser; 01.02.2013
comment
событие нажатия клавиши не запускается при нажатии клавиши Esc. Использование keydown / keyup выполнит эту работу. - person Vivek; 08.07.2015

На данный момент с Angular v4 это работает: (keyup.esc)="callback()"

person ktretyak    schedule 21.10.2017
comment
Это лучший и простой ответ! - person Kishore Sahasranaman; 04.01.2021

Мне удалось создать directive очистку непосредственно ng-model элемента ввода и правильно работать также в Firefox. Для этого мне нужно проверить, очищено ли уже значение (modelGetter(scope)), а также обернуть присвоение нулевому методу $timeout (чтобы применить его в следующем вызове дайджеста).

mod.directive('escClear', ['$timeout', '$parse', function($timeout, $parse) {
  return {
    link : function(scope, element, attributes, ctrl) {
      var modelGetter = $parse(attributes.ngModel);
      element.bind('keydown', function(e) {
        if (e.keyCode === $.ui.keyCode.ESCAPE && modelGetter(scope)) {
          $timeout(function() {
            scope.$apply(function () {modelGetter.assign(scope, '');});
          }, 0);
        }
      });
    }
  };
}]);

У меня $ свойство jQuery, не стесняйтесь заменять его магическим числом 27.

person icl7126    schedule 07.11.2015

Версия Angular 2, которая также обновляет ngModel

Директива

import { Directive, Output, EventEmitter, ElementRef, HostListener } from '@angular/core';

@Directive({
  selector: '[escapeInput]'
})
export class escapeInput {

  @Output() ngModelChange: EventEmitter<any> = new EventEmitter();
  private element: HTMLElement;
  private KEY_ESCAPE: number = 27;

  constructor(private elementRef: ElementRef) {
    this.element = elementRef.nativeElement;
  }

  @HostListener('keyup', ['$event']) onKeyDown(event) {
    if (event.keyCode == this.KEY_ESCAPE) {
      event.target.value = '';
      this.ngModelChange.emit(event.target.value);
    }
  }

}

использование

<input escapeInput class="form-control" [(ngModel)]="modelValue" type="text" />
person Erkin Djindjiev    schedule 14.07.2017