2

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.

Community
  • 1
  • 1
Watt
  • 3,118
  • 14
  • 54
  • 85

4 Answers4

9

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);
Mark Rajcok
  • 362,217
  • 114
  • 495
  • 492
  • Wondering if Can you answer 2 of this question http://stackoverflow.com/questions/17661176/how-to-create-angularjs-directive-to-get-jquery-dialog-with-submit-on-press-of-e/17680541#17680541 – Watt Jul 16 '13 at 15:21
  • @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 – Mohammad Umair Khan Aug 23 '13 at 04:34
  • @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. – Mark Rajcok Aug 23 '13 at 13:11
  • nothing is different I just dint get the point of setting and resetting focusInput which you did explain .. thanks alot mate – Mohammad Umair Khan Aug 24 '13 at 09:24
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

Stewie
  • 60,366
  • 20
  • 146
  • 113
  • Yup actually just got done reading through some of the trail of SO posts about this topic, here's I believe the same solution: http://stackoverflow.com/questions/14859266/input-autofocus-attribute/14859639#14859639 – shaunhusain Jul 11 '13 at 18:09
  • +1 For code and explanation. But Auto focus doesn't work when textbox is in a modal (popup). See your code with modal here http://plnkr.co/WKq83K . Please let me know if I missed something. – Watt Jul 11 '13 at 19:47
0

I have used the following url Building dialog service using bootstrap modal for customizing my alert and confirm boxes. Here I have a situation to autofocus the ok button by default. So I have used the following simple directive, and it works for me without any hassle, hope it helps to anyone.

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

Here you can customize the inner html of the element by using $compile option in the commented section

Kanagu
  • 606
  • 3
  • 9
  • 17
0

I wanted to make it as easy as possible to define which input field would get focus on modal opened, so I created an extension to the $modal provider named modal and put it in a separate module. Now whenever I want to focus something in a newly opened dialog, I simply write:

function MyController(modal) {
    var modalInstance = modal.openExtended( { 
        focus: "#categoryName",
        // ... more options
    } );
}

Now the only thing I have to do different is to use modal.openExtended instead of $modal.open and provide a focus parameter to the options.

The extension is as shown below:

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

Note that you will need to include the components module into your app, as such:

var app = angular.module('app', ['components', 'ui.bootstrap']);
JesperB
  • 4,625
  • 1
  • 36
  • 40