183
votes

I've seen a couple of questions in regards to bootstrap modals, but none exactly like this, so I'll go ahead.

I have a modal that I call onclick like so...

$(".modal-link").click(function(event){
  $("#modal-content").modal('show');
});

This works fine, but when I show the modal I want to focus on the first input element... In may case the first input element has an id of #photo_name.

So I tried

   $(".modal-link").click(function(event){
     $("#modal-content").modal('show');
     $("input#photo_name").focus();
   });

But this was to no avail. Lastly, I tried binding to the 'show' event but even so, the input won't focus. Lastly just for testing, as I had a suspiscion this is about the js loading order, I put in a setTimeout just to see if I delay a second, will the focus work, and yes, it works! But this method is obviously crap. Is there some way to have the same effect as below without using a setTimeout?

  $("#modal-content").on('show', function(event){
    window.setTimeout(function(){
      $(event.currentTarget).find('input#photo_name').first().focus()
    }, 0500);
  });
11

11 Answers

371
votes

Try this

Here is the old DEMO:

EDIT: (Here is a working DEMO with Bootstrap 3 and jQuery 1.8.3)

$(document).ready(function() {
    $('#modal-content').modal('show');
    $('#modal-content').on('shown', function() {
        $("#txtname").focus();
    })
});

Starting bootstrap 3 need to use shown.bs.modal event:

$('#modal-content').on('shown.bs.modal', function() {
    $("#txtname").focus();
})
75
votes

Just wanted to say that Bootstrap 3 handles this a bit differently. The event name is "shown.bs.modal".

$('#themodal').on('shown.bs.modal', function () {
   $("#txtname").focus();
});

or put the focus on the first visible input like this:

.modal('show').on('shown.bs.modal', function ()
{
    $('input:visible:first').focus();
})

http://getbootstrap.com/javascript/#modals

10
votes

I am using this in my layout to capture all modals and focus on the first input

  $('.modal').on('shown', function() {
     $(this).find('input').focus();
  });
9
votes

I had the same problem with bootstrap 3, focus when i click the link, but not when trigger the event with javascript. The solution:

$('#myModal').on('shown.bs.modal', function () {
    setTimeout(function(){
        $('#inputId').focus();
    }, 100);
});

Probably it´s something about the animation!

8
votes

I had problem to catch "shown.bs.modal" event.. And this is my solution which works perfect..

Instead simple on():

$('#modal').on 'shown.bs.modal', ->

Use on() with delegated element:

$('body').on 'shown.bs.modal', '#modal', ->
6
votes

Seems it is because modal animation is enabled (fade in class of the dialog), after calling .modal('show'), the dialog is not immediately visible, so it can't get focus at this time.

I can think of two ways to solve this problem:

  1. Remove fade from class, so the dialog is immediately visible after calling .modal('show'). You can see http://codebins.com/bin/4ldqp7x/4 for demo. (Sorry @keyur, I mistakenly edited and saved as new version of your example)
  2. Call focus() in shown event like what @keyur wrote.
4
votes

I've created a dynamic way to call each event automatically. It perfect to focus a field, because it call the event just once, removing it after use.

function modalEvents() {
    var modal = $('#modal');
    var events = ['show', 'shown', 'hide', 'hidden'];

    $(events).each(function (index, event) {
        modal.on(event + '.bs.modal', function (e) {
            var callback = modal.data(event + '-callback');
            if (typeof callback != 'undefined') {
                callback.call();
                modal.removeData(event + '-callback');
            }
        });
    });
}

You just need to call modalEvents() on document ready.

Use:

$('#modal').data('show-callback', function() {
    $("input#photo_name").focus();
});

So, you can use the same modal to load what you want without worry about remove events every time.

3
votes

I had the same problem with the bootstrap 3 and solved like this:

$('#myModal').on('shown.bs.modal', function (e) {
    $(this).find('input[type=text]:visible:first').focus();
})

$('#myModal').modal('show').trigger('shown');
0
votes

Bootstrap has added a loaded event.

https://getbootstrap.com/docs/3.3/javascript/#modals

capture the 'loaded.bs.modal' event on the modal

$('#mymodal').on('loaded.bs.modal', function(e) {
  // do cool stuff here all day… no need to change bootstrap
})
0
votes

Bootstrap modal show event

$('#modal-content').on('show.bs.modal', function() {
$("#txtname").focus();

})

-1
votes

A little cleaner and more modular solution might be:

$(document).ready(function(){
    $('.modal').success(function() { 
        $('input:text:visible:first').focus();
    });  
});

Or using your ID as an example instead:

$(document).ready(function(){
    $('#modal-content').modal('show').success(function() {
        $('input:text:visible:first').focus();
    });  
});

Hope that helps..