angular2: как управлять всем приложением только с клавиатуры?

Какой подход вы бы порекомендовали для управления всем приложением только с клавиатуры? Я нашел библиотеку Spotlight, но она зависит от enyojs, у которого, похоже, есть собственные компонентная модель и общий enyojs кажутся излишними.

Пока я слушаю события нажатия клавиш в app.component.ts:

@HostListener('window:keydown', ['$event']) onKeydown(event: any) {
  event.preventDefault();
  this.mainKeydownHandler.handle(event.keyCode);
}

Каждый компонент, который хочет обрабатывать события нажатия клавиши, регистрируется в обработчиках MainKeydownHandler, и когда происходит событие нажатия клавиши, MainKeydownHandler делегирует событие зарегистрированному обработчику. Соответствующий обработчик определяется классом document.activeElement (я не нашел более «углового2-подобного» способа получить текущий сфокусированный элемент) в методе handle MainKeydownHandler. Итак, теперь мне нужно добавить соответствующее имя класса к группе элементов, на которых я хочу сосредоточиться.

Кроме того, обработчик компонента получает все выбираемые элементы с помощью:

@ViewChildren('selectable') elements: QueryList<ElementRef>;

поэтому мне нужно добавить #selectable и класс с идентификатором обработчика к каждому элементу, на котором я хочу сосредоточиться. Затем обработчик компонента получает keyCode и определяет, какой элемент выбрать следующим или вернуться к ранее выбранному элементу из другого компонента и так далее.

Этот подход кажется неудобным, включает довольно много кода, когда новый компонент хочет обрабатывать события нажатия клавиш, и бывают ситуации, когда компонент полностью теряет фокус: когда я удаляю элемент из какого-то списка, а затем этот компонент перерисовывается (какой-то сервис или MainKeydownHandler мог запомнить, но это может привести к тому, что пользователю придется запоминать довольно много элементов при навигации по компонентам).

Есть ли лучший, более простой, более общий и более декларативный способ управления всем приложением angular2 только с помощью клавиатуры (события нажатия/нажатия клавиши)?

В качестве альтернативы разумно ли использовать Spotlight (с отделом enyojs) с angular2 для этого варианта использования? И можете ли вы предоставить работающий плункер с angular2+spotlight. Я не смог заставить эти два работать вместе.


person Petr Marek    schedule 07.12.2016    source источник
comment
Вы хотите перемещаться по элементам с помощью клавиатуры или иметь какие-то настраиваемые действия в ответ на события клавиатуры, как в игре?   -  person sabithpocker    schedule 07.12.2016
comment
просто навигация (вверх, вниз, вправо, влево) и выбор (ввод)   -  person Petr Marek    schedule 07.12.2016


Ответы (2)


Если вы хотите включить базовую навигацию с помощью клавиатуры, вы можете сделать это с помощью tabindex, что является стандартным способом. См. спецификацию

document.getElementById('mylist').focus();
:focus{
  border: 1px solid red;
  }
Press TAB to navigate.
<ul id="mylist" tabindex="-1">
    <li tabindex="1"> One </li>
    <li tabindex="2"> Two </li>
    <li tabindex="4"> Four </li>
    <li tabindex="3"> Three </li>
</ul>

Если вы хотите сделать это с помощью клавиш со стрелками, вам придется прослушивать keydown событие в документе и вручную focus() элементы с помощью javascript. Будет легче перемещаться вперед и назад, а не так прямо, чтобы найти элемент, который находится выше и ниже текущего элемента в макете. Вам нужно будет сравнить координаты x, y или смещения.

document.getElementById('mylist').focus();

window.onkeydown = function(e) {
  var curr = document.activeElement;
  var treeWalker = document.createTreeWalker(
    document.body,
    NodeFilter.SHOW_ELEMENT,
    { acceptNode: function(node) { return (node.tabIndex === -1)?NodeFilter.FILTER_SKIP: NodeFilter.FILTER_ACCEPT} },
    false
);
  treeWalker.currentNode = curr;
  
  if (e.keyCode == 39) {
     treeWalker.nextNode().focus();
  }
  if (e.keyCode == 37) {
     treeWalker.previousNode().focus();
  }
};
:focus {
  border: 1px solid red;
}
Press Right/Left arrow keys to navigate
<ul id="mylist" tabindex="-1">
  <li tabindex="1">One</li>
  <li tabindex="2">Two</li>
  <li tabindex="4">Four</li>
  <li tabindex="3">Three</li>
  <li>Not selectable</li>
  <li tabindex="5">Five</li>
</ul>

person sabithpocker    schedule 07.12.2016

Вы можете взглянуть на https://github.com/luke-chang/js-spatial-navigation Это общая библиотека пространственной навигации. Он должен легко интегрироваться с Angular.

Вы также можете проверить этот связанный SO: Перемещайтесь по пользовательскому интерфейсу, используя только клавиатуру

И это приложение Angular TV с пространственной навигацией: https://github.com/ahmednuaman/angular-tv-app

person Pre101    schedule 07.12.2016
comment
Я пытался создать телевизионное приложение, используя angular 4, но не смог использовать js-spacial-navigation. есть мысли как его использовать? - person Santosh; 05.03.2018
comment
Я не знаю! Мы (LG) создали ответвление библиотеки для использования с нашей инфраструктурой Enact. Он называется Spotlight и доступен на npm здесь: npmjs.com/package/@enact/spotlight Однако в первую очередь он предназначен для использования с React. - person Pre101; 10.05.2018