Почему фокус на текстовом поле не устанавливается внутри модального твитер-бутстрапа (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']);