Подтвердить что ты не робот

Angularjs: настройка фокуса на ранее скрытый элемент ввода внутри директивы

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

Я получил директиву angular, которая компилирует некоторый код html перед визуализацией. В html есть скрытый вход, который становится видимым только в том случае, если scope.isEditShown - true:

<input ng-show='isEditShown' type='text' value='{{content.name}}' class='title_edit'/>

Ввод появляется при вызове функции scope.titleChange. Эта функция (связанная с директивой ng-dblclick) просто устанавливает значение true для scope.isEditShown и пытается вызвать метод jQuery focus() для элемента ввода (ранее сохраненного в области в функции компоновщика с scope.input = $("input:text", ae);:

scope.isEditShown = true;
scope.input.focus();

Короче говоря, я хочу визуализировать ранее скрытый ввод, когда что-то дважды щелкнут, и дайте ему немедленный фокус. Непосредственный фокус необходим, потому что вход скрыт, когда он теряет фокус (я хочу, чтобы пользователь сразу мог редактировать входной контент. Когда пользователь щелкает, вход скрыт).

Проблема заключается в том, что кажется, что я не могу программно выделить фокус элемента ввода. После эксперимента я обнаружил, что при выполнении scope.isEditShown = true; вход еще не отображается (= angular js не показывает его в DOM), а установка фокуса с scope.input.focus(); на скрытый ввод ничего не делает. Когда элемент ввода, наконец, будет показан, он не сфокусирован.

Что такое angular способ сделать то, что я хочу? Когда я могу быть уверен, что мой ввод показан, и когда я могу называть его focus() эффективно? ПРИМЕЧАНИЕ. Если я использую scope.$apply(), прежде чем давать фокус на ввод, я получу исключение $apply already in progress. Если я сделаю безопасное применение, foucus не будет предоставлен. См. plunkr.

(ps: Я действительно хочу понять, поэтому я не собираюсь использовать сопутствующие библиотеки, которые автоматически делают это для меня)

4b9b3361

Ответ 1

Когда вы вносите изменения в какую-либо переменную, привязанную к данным, и вам нужно дождаться, когда произойдет соответствующий рендеринг, вам нужно использовать знаменитый setTimeout 0 (поочередно в Angular услуге $timeout).

Вот это plunkr, который показывает, как это сделать.

http://plnkr.co/edit/N9P7XHzQqJbQsnqNHDLm?p=preview