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

Отложить угловое выполнение часов после $digest (повышение DOM-события)

У меня есть часы, которые запускают событие DOM:

scope.$watch(function() { return controller.selected; }, function(selected) {
    if (selected) {
        $input.trigger('focus');
    }
});

Проблема в том, что у меня есть обработчик "focus", который выполняет scope.$apply.

$input.bind('focus', function() {
    scope.$apply(function() { controller.focused = true; });
});

Итак, когда мой $watch запускается изнутри $digest, он вызывает ошибку, потому что он пытается запустить еще один $digest.

Обходной путь, который у меня есть, - поставить триггер в $timeout.

scope.$watch(function() { return controller.selected; }, function(selected) {
    if (selected) {
        $timeout(function() { $input.trigger('focus'); });
    }
});

Это работает... до сих пор. Это правильный способ справиться с этим? Я не уверен, что это поймает каждый случай и хотел бы узнать, есть ли одобренный angular способ откусить часть кода после дайджеста.

Спасибо!

4b9b3361

Ответ 1

$timeout обычно используется для запуска чего-то после цикла дайджеста (и после браузера делает).

$timeout приведет к выполнению другого цикла дайджеста после выполнения функции. Если ваш trigger не влияет ни на что Angular, вы можете установить аргумент invokeApply на false, чтобы избежать запуска другого цикла дайджеста.

Если вы хотите, чтобы ваш обратный вызов выполнял до, браузер отображает: Если код поставлен в очередь с помощью $evalAsync из директивы, он должен запускаться после того, как DOM был обработан с помощью Angular, но до браузер делает. Однако, если код поставлен в очередь с помощью $evalAsync с контроллера, он будет запущен до того, как DOM будет обработан Angular (и до отображения браузера). См. Также fooobar.com/questions/18454/....

Ответ 2

Как и все говорят: "Вы не должны делать вещи DOM в своем контроллере.

Вот решение, которое применяет двустороннюю привязку данных к фокусу. Теперь ваш фокус связан с переменной. Поэтому, когда вы устанавливаете переменную в true, она фокусируется на соответствующем элементе, и когда элемент получает фокус, задается переменная.

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

Теперь мы успешно отделили фокус от кода контроллера. Он также заботится обо всех проблемах с таймаутом $(я думаю). Единственное, что вам нужно знать, это то, что вы не должны использовать одну и ту же переменную для привязки к фокусу двух разных элементов.

РЕДАКТИРОВАТЬ: Обновлен плунж, поскольку предыдущий не работал нормально.