Attach event handler to button in twitter bootstrap popover

34,786

Solution 1

I had the same problem, and, in my case, the $(body).on('click') workaround won't work, since the application has lotta click buttons.

I did the following instead. This way, we can limit the scope of the delegate event to just the parent of the popover element.

$('a.foo').popover({
    html: true,
    title: 'Hello',
    placement: 'bottom',
    content: '<button id="close-me">Close Me!</button>'
}).parent().delegate('button#close-me', 'click', function() {
    console.log('World!');
});

JS Fiddle: http://jsfiddle.net/dashk/5Yz7z/

P.S. I used this technique in within a Backbone.View in my application. Here's the snippet of the code in Fiddle, in case you're using this in Backbone.js as well...: http://jsfiddle.net/dashk/PA6wY/

EDITED In Bootstrap 2.3, you can specify a target container which popover will be added to. Now, instead of doing the .parent() locator, you can also listen to events specifically to the container... This can make the listener even more specific (Imagine creating a DIV that only exists to contain the popover.)

Solution 2

This should do it. This will take care of any existing and future button elements created inside an element with the .popover class:

$('body').on('click', '.popover button', function () {
    // code here
});

Solution 3

Very simple solution that worked for me is:

// suppose that popover is defined in HTML
$('a.foo').popover(); 

// when popover's content is shown
$('a.foo').on('shown.bs.popover', function() {
    // set what happens when user clicks on the button
    $("#my-button").on('click', function(){
        alert("clicked!!!");
    });
});

// when popover's content is hidden
$('a.foo').on('hidden.bs.popover', function(){
    // clear listeners
    $("#my-button").off('click');
});

Why this works: Basically popover's content has no listener until the popover is opened.

When popover is shown, bootstrap fires its event shown.bs.popover. We can attach an event handler on this event to $(a.foo) using the jQuery on method. So when popover is shown, the handler (callback) function is called. In this callback, we can attach event handlers to the content of the popover - for example: what happens when user clicks on this button inside the popover.

After popover is closed, it is good idea to remove all attached handlers to the popover's content. This is done via hidden.bs.popover handler, which removes handlers with jQuery .off method. This prevents event handlers inside the popover to be called twice (and more) when the popover is opened again...

Solution 4

Just to slightly update DashK's very good answer: .delegate() has been superseded by .on() as of jQuery 1.7 (see here).

$('a.foo').popover({
    html: true,
    title: 'Hello',
    placement: 'bottom',
    content: '<button id="close-me">Close Me!</button>'
}).parent().on('click', 'button#close-me', function() {
    console.log('World!');
});

See jsfiddle here: http://jsfiddle.net/smingers/nCKxs/2/

I have also had some issues with chaining the .on() method to $('a.foo'); if you experience such an issue, try adding it to the document, body, or html, e.g.:

$('a.foo').popover({
    html: true,
    title: 'Hello',
    placement: 'bottom',
    content: '<button id="close-me">Close Me!</button>'
});

$('body').on('click', 'button#close-me', function() {
    console.log('World!');
});

Solution 5

$('.btn-popover').parent().delegate('button#close-me','click', function(){
  alert('Hello');
});

If data attributes are set in static html the above method works fine. Thanks :)

Share:
34,786

Related videos on Youtube

Hailwood
Author by

Hailwood

I could tell you all about me... but I'd prefer to let my work do the talking for me!

Updated on March 14, 2020

Comments

  • Hailwood
    Hailwood about 4 years

    I am using the twitter bootstrap popovers,

    In the popover I am adding a button,

    I need to attach a click handler to the button, but the way popover works is each time it shows it removes and re-creates the element, instead of just showing/hiding it, hence removing any event handlers I have associated with said button.

    I am creating several popovers all with their own version of the button, so just applying a class to the popover won't work (unless I generate a different class for each one :/), the button may or may not have it's own ID, so cannot apply an ID.

    How can I apply a event handler to something in the contents of the twitter bootstrap popover?

    • Kevin B
      Kevin B over 11 years
      You have two options. #1: re-bind it after the popover opens, or #2 bind it using event delegation. What does the button need to do?
    • Hailwood
      Hailwood over 11 years
      Lots of different things, some submit forms (via js), some simply close the popover,
  • Hailwood
    Hailwood over 11 years
    That will only work if I want all the buttons to do the same thing
  • manishie
    manishie over 11 years
    Right, i'm sorry, I just noticed that point in your original post. Is there some reason that you can't give a specific class to each popover?
  • mccainz
    mccainz over 10 years
    Great answer for versions prior to 2.3, used this for 2.1.1 and it worked well.
  • tofirius
    tofirius almost 7 years
    Building on this answer in a similar vein, this worked for me, as well: $('a.foo').popover({ html: true, title: 'Hello', placement: 'bottom', content: '<button id="close-me">Close Me!</button>' }).parents('body').on('click','button#close-me',function(){ console.log('Popover button clicked!'); });
  • lomelisan
    lomelisan over 4 years
    @Hailwood why don't you use ids instead of classes? ids generated dynamically should do the job!