Почему фокус на текстовом поле не устанавливается внутри модального твитер-бутстрапа (popup) от AngularJS
Я пытался реализовать то, что предлагалось здесь, и другое подобное решение
Как установить фокус на поле ввода?
PLUNKER мой код с нерабочей автофокусом.
HTML
<body ng-controller='userNameController'>
<button class="btn" id="enterUsernameBtn" href="#userNameModal" role="button" class="btn" data-toggle="modal" title="Enter Username"
ng-click="focusInput=true">Enter Username</button>
<!-- UserName Modal -->
<div id="userNameModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="userNameModalLabel"
aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="userNameModalLabel">Enter your username</h3>
</div>
<div class="modal-body">
<div class="input-append">
<input class="pull-left" id="userIdTextBox" type="text"
ng-model="userName1" ng-minlength="1" ng-trim="true" focus-me="focusInput"/>
</div>
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="{{whatToDismiss}}" aria-hidden="true" ng-click="submitUserName()">Submit</button>
</div>
</div>
</body>
JavaScript
var app = angular.module('abcApp',[]);
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();
});
}
});
}
};
});
app.controller('userNameController',function ($scope)
{
$scope.whatToDismiss=''; // workaround not to close the modal if it is an invalid input
$scope.focusInput=false;
$scope.submitUserName= function ()
{
if($scope.userName1===undefined || $scope.userName1==="")
{
alert("Invalid Input");
return;
}
alert("username entered"+$scope.userName1);
$scope.whatToDismiss='modal';
}
});
Ни одно из решений не работает для меня. Я как-то фокусируюсь на текстовом поле, когда модально открывается, но затем я не больше получает значение userName1
через ng-model
. После реализации директивы focusMe
userName1
всегда undefined.
Изменить
Попытка
Можно ли использовать ng-модель с изолированной областью?
Потому что кажется, что ng-model
не будет работать для вышеуказанного решения
Между тем, каждый приходит с ответом на мой вопрос "Как установить автофокус в текстовое поле внутри twitter-bootstrap modal и в состоянии получить значение, введенное в это текстовое поле через ng-model" , пожалуйста, поделитесь.
Ответы
Ответ 1
Я изменил ваш плукер, http://plnkr.co/WKq83K и создал этот рабочий плункер: http://plnkr.co/edit/fsBjsW?p=preview
Изменения следующие:
Используйте focus-me
, а не focusMe
:
<input class="pull-left" id="userIdTextBox" type="text" ng-model="userName1"
ng-minlength="1" ng-trim="true" focus-me="focusInput">
Установите значение focusInput
в true
, когда откроется диалоговое окно:
<button class="btn" id="enterUsernameBtn" href="#userNameModal" role="button"
class="btn" data-toggle="modal" title="Enter Username"
ng-click="focusInput=true">Enter Username</button>
Верните его обратно в false
, когда будет отправлено диалоговое окно:
$scope.submitUserName= function() {
$scope.focusInput = false;
...
или отменено:
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"
ng-click="focusInput=false">x</button>
$timeout
нужно немного подождать для рендеринга модальности. Значения менее 480 не работают, поэтому я использовал что-то большее, 700:
$timeout(function() {
element.focus();
}, 700);
Ответ 2
Директива focusMe, которую вы нашли в этой статье, не предназначена для использования с ng-моделью без каких-либо изменений. Эта директива определяет изолированную область, поэтому ngModel не распространяется вверх в область родительского контроллера.
Чтобы исправить это, самое простое решение - это просто переопределить вашу директиву, чтобы не использовать отдельную область действия, и получить значение атрибута focusMe через функцию привязки attrs
:
app.directive('_focusMe', function($timeout) {
return function(scope, element, attrs) {
scope.$watch(attrs.focusMe, function(value) {
if(value) {
$timeout(function() {
element.focus();
}, 20);
}
});
};
});
PLUNKER
Ответ 3
Я использовал следующий url Создание диалогового окна с использованием бутстрапового модального для настройки моих предупреждений и подтверждений. Здесь у меня есть ситуация, когда автофокусировка кнопки ok по умолчанию. Поэтому я использовал следующую простую директиву, и она работает для меня без каких-либо хлопот, надеюсь, что это поможет кому угодно.
myApp.directive('focusMe', function($timeout, $compile) {
return {
link: function (scope, element, attrs) {
scope.$watch(attrs.focusMe, function(val) {
// element.html(anyHtmlHere);
// $compile(element.contents())(scope);
$timeout(function() {
element[0].focus();
}, 20);
});
}
};
});
Здесь вы можете настроить внутренний html элемента с помощью опции $compile в разделе комментариев
Ответ 4
Мне хотелось как можно проще определить, какое поле ввода будет сосредоточено на модальном открытии, поэтому я создал расширение для провайдера $modal
с именем modal
и поместил его в отдельный модуль. Теперь, когда я хочу что-то сфокусировать во вновь открывшемся диалоговом окне, я просто пишу:
function MyController(modal) {
var modalInstance = modal.openExtended( {
focus: "#categoryName",
// ... more options
} );
}
Теперь единственное, что мне нужно сделать, это использовать modal.openExtended
вместо $modal.open
и предоставить параметры focus
для параметров.
Расширение показано ниже:
angular.module('components', ['ui.bootstrap'])
.service('modal', function($modal, $timeout) {
var extended = angular.extend( $modal );
$modal.openExtended = function( modalOptions ) {
var modalInstance = $modal.open( modalOptions );
if ( typeof( modalOptions.focus ) != "undefined" ) {
modalInstance.opened.then( function() {
$timeout( function() {
$( modalOptions.focus ).focus();
// The interval of 100 millis below is somewhat arbitrary.
// Use something higher if the focus doesn't always work
}, 100 );
});
}
return modalInstance;
};
return extended;
});
Обратите внимание, что вам нужно будет включить модуль components
в ваше приложение:
var app = angular.module('app', ['components', 'ui.bootstrap']);