Why focus on textbox is not set inside a twitter-bootstrap modal (popup) by AngularJS

10,065

Solution 1

I modified your plunker, http://plnkr.co/WKq83K, and created this working plunker: http://plnkr.co/edit/fsBjsW?p=preview

Changes are as follows:

Use focus-me, not focusMe:

<input class="pull-left" id="userIdTextBox" type="text" ng-model="userName1"
 ng-minlength="1" ng-trim="true" focus-me="focusInput">

Set focusInput to true when the dialog is opened:

<button class="btn" id="enterUsernameBtn" href="#userNameModal" role="button"
 class="btn" data-toggle="modal" title="Enter Username" 
 ng-click="focusInput=true">Enter Username</button>

Set it back to false when the dialog is submitted:

$scope.submitUserName= function() {    
   $scope.focusInput = false;
   ...

or cancelled:

<button type="button" class="close" data-dismiss="modal" aria-hidden="true"
 ng-click="focusInput=false">x</button>

$timeout needs to wait a bit for the modal to render. Values less than 480 did not appear to work, so I used something larger, 700:

$timeout(function() {
   element.focus();
 }, 700);

Solution 2

focusMe directive that you've found in that post is not meant to be used with ng-model without some changes. That directive defines isolated scope so ngModel is not propagated upwards to the parent controller scope.

To remedy this the easiest solution is simply redefine your directive not to use separate scope, and to fetch the focusMe attribute value through linking function's attrs object:

app.directive('_focusMe', function($timeout) {
  return function(scope, element, attrs) {
    scope.$watch(attrs.focusMe, function(value) {
      if(value) {
        $timeout(function() {
          element.focus();
        }, 20);
      }
    });
  };
});

PLUNKER

Share:
10,065
Watt
Author by

Watt

Updated on July 17, 2022

Comments

  • Watt
    Watt almost 2 years

    I have been trying to implement what suggested here and other similar solution How to set focus on input field?

    PLUNKER my code with non-working autofocus.

    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';
    
      }
    });  
    

    None of solution is working for me. I somehow get the focus to set on textbox whenever modal opens, but then I no more get value of userName1 through ng-model. After implementing focusMe directive userName1 is always undefined.

    Edit

    Going to try this Can I use ng-model with isolated scope?

    Because it seems ng-model won't work for above solution

    Meanwhile, anyone comes with answer to my question "How to set auto-focus to textbox inside twitter-bootstrap modal and able to get value entered in that textbox through ng-model" please share.

  • shaunhusain
    shaunhusain almost 11 years
    Yup actually just got done reading through some of the trail of SO posts about this topic, here's I believe the same solution: stackoverflow.com/questions/14859266/input-autofocus-attribu‌​te/…
  • Watt
    Watt almost 11 years
    +1 For code and explanation. But Auto focus doesn't work when textbox is in a modal (popup). See your code with modal here plnkr.co/WKq83K . Please let me know if I missed something.
  • Watt
    Watt almost 11 years
    Wondering if Can you answer 2 of this question stackoverflow.com/questions/17661176/…
  • Mohammad Umair Khan
    Mohammad Umair Khan over 10 years
    @Mark, Guys I understand the whole point except for the piece that why are we setting the variable to true and false upon opening and closing respectively, I can get it to work by only providing focus-me='true' on what i need to focus and it works okay, maybe i am missing the point here PLUS i am also able to get the value from ng-model in my input .. thanks for the discussion guys
  • Mark Rajcok
    Mark Rajcok over 10 years
    @MohammadUmairKhan, the FocusMe directive is hopefully generic enough to be used in other situations (e.g., no modal), where it is necessary to detect a change from false to true in order to set the focus (again) on a element... hence the reason we go through the trouble of setting it to false. "I am able to get the value from ng-model in my input" -- okay, but you didn't say/show how, or what is different.
  • Mohammad Umair Khan
    Mohammad Umair Khan over 10 years
    nothing is different I just dint get the point of setting and resetting focusInput which you did explain .. thanks alot mate