#angularjs #angularjs-scope
#angularjs #angularjs-область
Вопрос:
Возможно ли установить фокус поля ввода через контроллер после загрузки данных (в данном случае через $resource)?
Ввод скрыт с помощью ng-show до тех пор, пока данные не будут возвращены из API, но я не могу найти способ установить фокус на ввод. Я знаю имя ng-model для ввода и имя ввода, что означает, что я мог бы сделать это с помощью jQuery, но я бы предпочел сделать это, если возможно, с помощью AngularJS.
Я перепробовал здесь много примеров директив, но все они, похоже, ориентированы на ng-фокус до 1.2, полагаются на ng-щелчок сначала с кнопки (в моем случае этого не может быть) или просто не работают.
Любые советы с благодарностью получены.
Комментарии:
1. Если вы делаете это при загрузке страницы, некоторые браузеры не позволят вам сделать это по соображениям безопасности.
2. Я надеюсь, что нет, я бы предпочел отключить вызов, когда я знаю, что данные вернулись из API, но я не вижу, как заставить это работать даже с помощью jQuery.
Ответ №1:
Это простая директива, которая может сработать для вас
<input focus-on="!!myResourceData" />
.directive('focusOn',function($timeout) {
return {
restrict : 'A',
link : function($scope,$element,$attr) {
$scope.$watch($attr.focusOn,function(_focusVal) {
$timeout(function() {
_focusVal ? $element[0].focus() :
$element[0].blur();
});
});
}
}
})
Комментарии:
1. Да! Вот и все — возможно, я делал это неправильно, поскольку я видел что-то подобное, но не использовался!! в теге HTML. Спасибо 🙂
2. Почему
setTimeout
? Это потому, что этот цикл дайджеста еще не показывает элемент?$timeout
это было бы чисто выполнено, не прибегая к произвольным временам.3. @spenhil- вы совершенно правы. Я обновил пример. Спасибо.
4. Я не знаю, связано ли это с тем, что я использовал другую версию angular или что-то еще, но мне пришлось изменить
$element.focus()
$element[0].focus()
и то же самоеblur()
, прежде чем это сработало. Кроме этого, это спасло мне день.5. Вам также может потребоваться установить
$element[0].select()
, но самая большая проблема заключается в том, что он, скорее всего, не будет работать без указания задержки по времени ожидания, так как обаng-hide
иng-show
отображаются с определенной анимацией (ng-hide-animate), поэтому в течение переходного периода вы не сможете установить фокус. В идеале вы должны получить переходный период от элемента, но я надеюсь, что указание некоторой фиксированной (50 мс) задержки может сработать и для вас.
Ответ №2:
Я расширил ответ для работы с angular ng-show
и ng-hide
app.directive('focusOnShow', function($timeout) {
return {
restrict: 'A',
link: function($scope, $element, $attr) {
if ($attr.ngShow){
$scope.$watch($attr.ngShow, function(newValue){
if(newValue){
$timeout(function(){
$element[0].focus();
}, 0);
}
})
}
if ($attr.ngHide){
$scope.$watch($attr.ngHide, function(newValue){
if(!newValue){
$timeout(function(){
$element[0].focus();
}, 0);
}
})
}
}
};
})
Все, что вам нужно, это добавить атрибут focus-on-show
<input type="text" ng-show="editing" focus-on-show />
Комментарии:
1. Это ИМЕННО то, что я искал, потрясающий код, который вы там сделали! Поздравляю!
2. Именно то, что я искал, это единственный ответ, который работает до сих пор
3. Это отлично работает в браузере, но на iPhone оно не работает
Ответ №3:
Основываясь на ответе koolunix, если вы хотите сфокусировать только элементы ввода, также может быть полезно найти первый элемент ввода, который является дочерним элементом элемента с директивой focus-on .
Это полезно в случае, когда внешняя библиотека абстрагирует входной элемент с помощью директив и шаблонов.
.directive('focusOn', function ($timeout) {
return {
restrict: 'A',
priority: -100,
link: function ($scope, $element, $attr) {
$scope.$watch($attr.focusOn,
function (_focusVal) {
$timeout( function () {
var inputElement = $element.is('input')
? $element
: $element.find('input');
_focusVal ? inputElement.focus()
: inputElement.blur();
});
}
);
}
};
});
Ответ №4:
вы должны использовать тайм-аут в своем контроллере, чтобы он был отображен до того, как вот аналогичный пример с полем поиска, которое скрыто по умолчанию
HTML:
<input ng-show="vm.isActive" id="searchInputBox" ></input>
<input type="button" ng-click="vm.toggleActiveInactive();">
Контроллер:
vm.isActive=false;
vm.toggleActiveInactive=toggleActiveInactive; // vm= viewmodel
function toggleActiveInactive() {
if(vm.isActive==true){
vm.isActive=false;
}else{
vm.isActive=true;
$timeout(function(){
document.getElementById('searchBoxInput').focus()
}, 10 );
}
}
Ответ №5:
Другая версия этого для Angular.io
import {Directive, ElementRef, Input, OnChanges, SimpleChanges} from '@angular/core';
//Directive to that toggles focus from boolean value set with focusOn
@Directive({
selector: '[focusOn]'
})
export class FocusOnDirective implements OnChanges {
@Input('focusOn') setFocus: boolean;
constructor(private hostElement: ElementRef) {}
ngOnChanges(changes : SimpleChanges) {
(!!changes.setFocus amp;amp; !!changes.setFocus.currentValue) ?
this.hostElement.nativeElement.focus() :
this.hostElement.nativeElement.blur();
}
}