- Когда модальное окно открыто, установите фокус на предварительно определенный <input> внутри этого модального окна.
Определите директиву и задайте ей $ watch свойство / триггер, чтобы он знал, когда нужно сфокусировать элемент:
Name: <input type="text" focus-me="shouldBeOpen">
app.directive('focusMe', ['$timeout', '$parse', function ($timeout, $parse) {
return {
//scope: true, // optionally create a child scope
link: function (scope, element, attrs) {
var model = $parse(attrs.focusMe);
scope.$watch(model, function (value) {
console.log('value=', value);
if (value === true) {
$timeout(function () {
element[0].focus();
});
}
});
// to address @blesh's comment, set attribute value to 'false'
// on blur event:
element.bind('blur', function () {
console.log('blur');
scope.$apply(model.assign(scope, false));
});
}
};
}]);
Plunker
$ Timeout, кажется, необходим, чтобы дать модальное время для рендеринга.
'2.' Каждый раз, когда <input> становится видимым (например, нажатием какой-либо кнопки), установите фокус на него.
Создайте директиву, по сути, похожую на приведенную выше Следите за некоторым свойством контекста, и когда оно станет истинным (установите его в вашем обработчике ng-click), выполните element[0].focus()
. В зависимости от вашего варианта использования вам может понадобиться или не потребоваться тайм-аут в $ для этого:
<button class="btn" ng-click="showForm=true; focusInput=true">show form and
focus input</button>
<div ng-show="showForm">
<input type="text" ng-model="myInput" focus-me="focusInput"> {{ myInput }}
<button class="btn" ng-click="showForm=false">hide form</button>
</div>
app.directive('focusMe', function($timeout) {
return {
link: function(scope, element, attrs) {
scope.$watch(attrs.focusMe, function(value) {
if(value === true) {
console.log('value=',value);
//$timeout(function() {
element[0].focus();
scope[attrs.focusMe] = false;
//});
}
});
}
};
});
Plunker
Обновление 7/2013 : я видел, как несколько человек использовали мои оригинальные директивы для области видимости, а затем столкнулись с проблемами во встроенных полях ввода (т. Е. В поле ввода в модальном поле). Директива без новой области (или, возможно, с новой дочерней областью) должна облегчить некоторые проблемы. Поэтому выше я обновил ответ, чтобы не использовать изолирующие области. Ниже оригинальный ответ:
Оригинальный ответ для 1., используя область выделения:
Name: <input type="text" focus-me="{{shouldBeOpen}}">
app.directive('focusMe', function($timeout) {
return {
scope: { trigger: '@focusMe' },
link: function(scope, element) {
scope.$watch('trigger', function(value) {
if(value === "true") {
$timeout(function() {
element[0].focus();
});
}
});
}
};
});
Плункер .
Исходный ответ для 2. с использованием изолированной области:
<button class="btn" ng-click="showForm=true; focusInput=true">show form and
focus input</button>
<div ng-show="showForm">
<input type="text" focus-me="focusInput">
<button class="btn" ng-click="showForm=false">hide form</button>
</div>
app.directive('focusMe', function($timeout) {
return {
scope: { trigger: '=focusMe' },
link: function(scope, element) {
scope.$watch('trigger', function(value) {
if(value === true) {
//console.log('trigger',value);
//$timeout(function() {
element[0].focus();
scope.trigger = false;
//});
}
});
}
};
});
Плункер .
Так как нам нужно сбросить свойство trigger / focusInput в директиве, '=' используется для двусторонней привязки данных. В первой директиве «@» было достаточно. Также обратите внимание, что при использовании «@» мы сравниваем значение триггера с «истиной», поскольку @ всегда приводит к строке.
ng-model
в поле ввода, значение модели будет потеряно, когда я использую эту директиву без использования области видимости. Проблема не произойдет, если я попробую версию Джоша без изолированной области видимости. Все еще новичок, и я хотел бы понять разницу. Вот Plunker, который показывает это.value != "true"
, и это, казалось, решило мою проблему.(РЕДАКТИРОВАТЬ: я добавил обновленное решение ниже этого объяснения)
Марк Райкок - человек ... и его ответ - правильный ответ, но
унего был недостаток (извините, Марк) ...... Попробуйте использовать логическое значение, чтобы сфокусироваться на входе, затем размыть вход, затем попробуйте использовать его, чтобы снова сфокусировать ввод. Это не сработает, если вы не сбросите логическое значение на false, затем $ digest, а затем не сбросите его на true. Даже если вы используете сравнение строк в своем выражении, вы будете вынуждены изменить строку на что-то другое, $ digest, а затем изменить ее обратно.(Это было решено с помощью обработчика событий размытия.)Поэтому я предлагаю это альтернативное решение:
Используйте событие, забытое свойство Angular.
В конце концов, JavaScript любит события. События по своей сути слабо связаны, и, что еще лучше, вы избегаете добавления других $ watch к вашему $ digest.
Так что теперь вы можете использовать это так:
а затем в любом месте вашего приложения ...
Это потрясающе, потому что вы можете делать все что угодно с чем-то вроде этого. С одной стороны, вы можете связать с событиями, которые уже существуют. Во-вторых, вы начинаете делать что-то умное, публикуя события в разных частях вашего приложения, на которые могут подписаться другие части вашего приложения.
Во всяком случае, этот тип вещей кричит мне «событие, управляемое». Я думаю, как разработчики Angular, мы очень стараемся вбить колышки в форме $ scope в отверстия формы событий.
Это лучшее решение? Я не знаю. Это решение.
Обновленное решение
После комментария @ ShimonRachlenko ниже я немного изменил свой метод. Теперь я использую комбинацию службы и директивы, которая обрабатывает событие "за сценой":
Помимо этого, это тот же принцип, изложенный выше.
Вот быстрое демо Plunk
Применение
Источник
источник
$broadcast
с ,$timeout
если вы хотите , чтобы это работало на входе контроллера. В противном случае хорошее решение.Я нашел некоторые другие ответы слишком сложными, когда все, что вам действительно нужно, это
использование
Мы используем тайм-аут, чтобы позволить объектам в домене визуализироваться, даже если он равен нулю, он, по крайней мере, ждет этого - таким образом это работает в модальных моделях и еще много чего.
источник
ng-click
: скажем, нажатие кнопки имеетng-click="showInput = !showInput
на вашем входе. Затем, на ваш фактический вклад, добавьтеng-if="showInput"
. Переключение кнопки заставит директиву перезапускаться каждый раз. У меня была проблема с этим, поскольку я использовал,ng-show
который является неправильным подходом.HTML имеет атрибут
autofocus
.http://www.w3schools.com/tags/att_input_autofocus.asp
источник
Вы также можете использовать функциональность jqlite, встроенную в angular.
angular.element('.selector').trigger('focus');
источник
Looking up elements via selectors is not supported by jqLite!
Это хорошо работает и угловой способ фокусировки ввода управления
Это хотя и не чисто угловой способ выполнения задачи, но синтаксис следует угловому стилю. Jquery играет косвенную роль и напрямую обращается к DOM, используя Angular (jQLite => JQuery Light).
При необходимости этот код можно легко поместить в простую угловую директиву, где элемент доступен напрямую.
источник
Looking up elements via selectors is not supported by jqLite!
angular.element
становится оболочкой для$() / jQuery()
. Так что без этого это не сработает, и вы все равно просто используете jQuery (но поправьте меня, если я ошибаюсь)Я не думаю, что $ timeout - это хороший способ сфокусировать элемент на создании. Вот метод, использующий встроенную угловую функциональность, вырытую из темных глубин угловых документов. Обратите внимание, как атрибут «ссылка» может быть разделен на «pre» и «post» для функций pre-link и post-link.
Рабочий пример: http://plnkr.co/edit/Fj59GB
Полная директива AngularJS Документы: https://docs.angularjs.org/api/ng/service/$compile
источник
Вот мое оригинальное решение:
plunker
И HTML:
Что оно делает:
Он фокусирует ввод, когда он становится видимым с помощью ng-show. Нет необходимости использовать $ watch или $ здесь.
источник
Недавно я написал директиву о двухстороннем связывании фокуса, как и модель.
Вы можете использовать директиву focus следующим образом:
Если вы сделаете переменную области видимости someFocusVariable
true
где-нибудь в вашем контроллере, ввод будет сфокусирован. И если вы хотите «размыть» ваш ввод, тогда для someFocusVariable можно установить значение false. Это как первый ответ Марка Райкока, но с двусторонним связыванием.Вот директива:
Применение:
Вот скрипка:
http://fiddle.jshell.net/ubenzer/9FSL4/8/
источник
Для тех, кто использует Angular с плагином Bootstrap:
http://angular-ui.github.io/bootstrap/#/modal
Вы можете подключиться к
opened
обещанию модального экземпляра:источник
$timeout
с50ms
нуждается в вместо0
.Я нашел полезным использовать общее выражение. Таким образом, вы можете делать такие вещи, как автоматическое перемещение фокуса, когда введенный текст действителен
Или автоматически фокусироваться, когда пользователь заполняет поле фиксированной длины
И конечно же фокус после загрузки
Код для директивы:
источник
Не воскрешать зомби и не вставлять мою собственную директиву (хорошо, это именно то, что я делаю):
https://github.com/hiebj/ng-focus-if
http://plnkr.co/edit/MJS3zRk079Mu72o5A9l6?p=preview
источник
Во-первых, официальный способ сосредоточиться на дорожной карте для 1.1 . Между тем, вы можете написать директиву для реализации настроек фокуса.
Во-вторых, для фокусировки на элементе после того, как он стал видимым, требуется обходной путь. Просто отложите ваш вызов элемента focus () с помощью
$timeout
.Поскольку существует та же проблема controller-modizes-DOM для фокусировки, размытия и выделения, я предлагаю иметь
ng-target
директиву:Угловая тема здесь: http://goo.gl/ipsx4 , а более подробная информация опубликована здесь: http://goo.gl/4rdZa
Следующая директива создаст
.focus()
функцию внутри вашего контроллера, как указано вашимng-target
атрибутом. (Это создает.blur()
и.select()
тоже.) Демо: http://jsfiddle.net/bseib/WUcQX/источник
ngFocus
- это способ обработкиfocus
событий, а не способ установить фокус на элементе.Вместо создания своей собственной директивы можно просто использовать функции javascript для достижения цели.
Вот пример.
В HTML-файл:
В файле javascript, например, в контроллере, где вы хотите активировать фокус:
источник
Если вы просто хотели простой фокус, которым управлял нг-клик.
Html:
Директива:
источник
Простой, который хорошо работает с модалами:
пример
источник
Вы можете просто создать директиву, которая заставляет сосредоточиться на украшенном элементе на postLinking:
Тогда в вашем HTML:
Это будет работать для модальных элементов и переключаемых элементов ng-if, а не для ng-show, поскольку postLinking происходит только при обработке HTML.
источник
У Марка и Блеша прекрасные ответы; однако у Марка есть недостаток, на который указывает Блеш (помимо того, что он сложен для реализации), и я чувствую, что ответ Блеша имеет семантическую ошибку при создании службы, которая конкретно направляет запрос фокуса на внешний интерфейс, когда на самом деле все, что ему нужно, - это способ отложить событие, пока все директивы не будут прослушаны.
Итак, вот что я в итоге сделал, что во многом зависит от ответа Blesh, но разделяет семантику события контроллера и службы «после загрузки».
Это позволяет легко перехватывать событие контроллера для других вещей, помимо простой фокусировки на конкретном элементе, а также позволяет нести служебную нагрузку функции «после загрузки», только если это необходимо, чего во многих случаях может не быть.
Применение
Источник
источник
Это также возможно использовать
ngModelController
. Работа с 1.6+ (не знаю со старыми версиями).HTML
JS
-
NB. В зависимости от контекста вам, возможно, придется включить функцию тайм-аута.
NB²: При использовании
controllerAs
это почти то же самое. Просто заменитеname="myForm"
наname="vm.myForm"
и в JSvm.myForm.myText.$$element.focus();
.источник
Наверное, самое простое решение по возрасту ES6.
Добавление следующей директивы liner делает HTML-атрибут autofocus эффективным в Angular.js.
Теперь вы можете просто использовать синтаксис автофокуса HTML5, например:
источник
.directive('autofocus', ['$timeout', ($timeout) => ({link: (_, e) => $timeout(() => e[0].focus())})])
Просто новичок здесь, но я был в состоянии заставить его работать в ui.bootstrap.modal с этой директивой:
и в методе $ modal.open я использовал следующие элементы, чтобы указать элемент, на который следует поместить фокус:
на шаблоне у меня есть это:
источник
Следующая директива сработала для меня. Используйте тот же атрибут html автофокуса для ввода.
источник
Если вы используете modalInstance и у вас есть объект, вы можете использовать «затем» для выполнения действий после открытия модального. Если вы не используете modalInstance и жестко запрограммированы, чтобы открыть модал, вы можете использовать событие. Тайм-аут $ не является хорошим решением.
Вы можете сделать (Bootstrap3):
В modalInstance вы можете посмотреть на библиотеку, как выполнить код после открытия модального.
Не используйте $ timeout, как это, $ timeout может быть 0, 1, 10, 30, 50, 200 или более, это будет зависеть от клиентского компьютера и процесса открытия модального режима.
Не используйте $ timeout, пусть метод скажет вам, когда вы можете сосредоточиться;)
Я надеюсь, что это поможет! :)
источник
Весь предыдущий ответ не работает, если нужный элемент фокуса вставлен в шаблон директивы. Следующая директива подходит как для простого элемента, так и для элемента, вставленного в директиву (я написал ее на машинописи ). он принимает селектор для внутреннего фокусируемого элемента. если вам просто нужно сфокусировать элемент self - не отправляйте параметр селектора в директиву:
}
пример использования для простого элемента:
пример использования для внутреннего элемента (обычно для динамического внедренного элемента, такого как директива с шаблоном):
Вы можете использовать любой селектор jQuery вместо «ввода»
источник
Я редактирую директиву focusMe Марка Райкока для работы с несколькими фокусами в одном элементе.
HTML:
в контроллере AngularJs:
Директива AngulaJS:
источник
Я хочу внести свой вклад в эту дискуссию после того, как искал лучшее решение и не нашел его, а вместо этого создал его.
Критерии: 1. Решение должно быть независимым от области действия родительского контроллера для увеличения возможности повторного использования. 2. Избегайте использования $ watch для отслеживания некоторых условий, это является медленным, увеличивает размер цикла дайджеста и усложняет тестирование. 3. Избегайте $ timeout или $ scope. $ Apply () для запуска дайджест-цикла. 4. Элемент ввода присутствует внутри элемента, в котором используется директива open.
Это решение мне понравилось больше всего:
Директива:
Html:
Я надеюсь, что это поможет кому-то там!
источник
Это легко .. попробуйте это
HTML
Javascript
источник
Если вы хотите установить фокус на конкретный элемент, вы можете использовать подход ниже.
Создайте сервис под названием
focus
.Введите его в контроллер, откуда вы хотите позвонить.
Позвоните в эту службу.
источник
Я думаю, что директива не нужна. Используйте HTML id и атрибуты класса, чтобы выбрать необходимый элемент, и попросите службу использовать document.getElementById или document.querySelector для применения фокуса (или эквивалентов jQuery).
Разметка - это стандартные HTML / угловые директивы с добавленными идентификаторами / классами для выбора.
Контроллер транслирует событие
В UI сервис использует querySelector - если есть несколько совпадений (скажем, из-за класса), он вернет только первое
Вы можете использовать $ timeout () для запуска цикла дайджеста.
источник
Просто добавляю кофе.
источник