Search code examples
javascriptjquerytwitter-bootstrapbootstrap-popover

Dynamically creating buttons with popovers


I try to create buttons with popovers via JS dynamically. So far so good but I can't make it to get Div content attached to the popovers. They show up if I press the button but except of the headline they are just empty. Therefore I guess the problem lies in the //Append newDiv to Popovercontent - Part. But exactly with this function I am able to append div boxes to my popovers statically.

HTML:

<table id="table">
   <tr>
      <th>Col 1</th>
      <th>Col 2</th>
      <th>Col 3</th>
   </tr>
   <tr>
      <td></td>
      <td>
         <div id="div" style="display:none">
            <input type="checkbox"> Label 1</input><br>
            <input type="checkbox"> Label 2</input>
         </div>
      </td>
      <td style="text-align: center; vertical-align: middle;">
         <button data-toggle="popover" id="btn1" data-original-title="Popover" data-html="true" data-placement="bottom" type="button" class="btn btn-default" aria-label="Left Align">
            <span class="glyphicon glyphicon-chevron-down" aria-hidden="true"></span>
         </button>
      </td>
   </tr>
</table>

JS:

$("#btn1").popover({
   html: true,
   content: function() {
      return $("#div").html();
   }
});

var id = 2;

function addButton() {

//Creating HTML-Code for popovers
var newHTML = "<div style='display:none' id = 'newDiv" + id + "'>";
for (i = 0; i < 2; i++) {
    newHTML += "<input type=\"checkbox\" name=\"name" + id + i + "\">Label" + i + "</input><br>";
}
newHTML += "</div><button data-toggle=\"popover\" id=\"btn" + id + "\" data-original-title=\"Popover\" data-html=\"true\" data-placement=\"bottom\" type=\"button\" class=\"btn btn-default\" aria-label=\"Left Align\">";
newHTML += "<span class=\"glyphicon glyphicon-chevron-down\" aria-hidden=\"true\"></span></button>";

//Creating new Element
var trhtml = document.getElementById("table").insertRow();
var tdhtml = document.createElement("td");
tdhtml.style = "text-align: center; vertical-align: middle;";
tdhtml.innerHTML = newHTML;
trhtml.appendChild(tdhtml);

//Initialize new Popover
$('[data-toggle="popover"]').popover();

//Append newDiv to Popovercontent
$("#btn" + id).popover({
   html: true,
   content: function() {
      return $("#newDiv" + id).html();
  }
});

id=id+1;
}

Thank you very much!


Solution

  • You are facing this problem because are binding id inside popover content callback and then you are using variable id to create jquery selector $("#newDiv" + id).html()

    But the id variable is incremented each time, When the actual popover event called it receive id value NoOfRowInTable+1 for all popover content function calllback. For example if you have called addButton() 2 time the value of id inside popover content callback will be revived as 4 for all popover content callback function.

    You can find a better explanation here

    JavaScript closure inside loops – simple practical example

    Although for your example you don't need to make a hidden div with some id you can create html String for checkboxes and then add it to popover content callback .

    Here is working demo

    EDIT : Use .bind() to bind id properly

    $("#btn1").popover({
      html: true,
      content: function() {
        return $("#div").html();
      }
    });
    
    var id = 2;
    
    $("#btn1").popover({
      html: true,
      content: function() {
        return $("#div").html();
      }
    });
    
    var id = 2;
    
    function addButton() {
    
      //Creating HTML-Code for popovers
      var newHTML = "<div style='display:none' id = 'newDiv" + id + "'>";
      for (i = 0; i < 2; i++) {
        newHTML += "<input type=\"checkbox\" name=\"name" + id + i + "\">Label" + i + "</input><br>";
      }
      newHTML += "</div><button data-toggle=\"popover\" id=\"btn" + id + "\" data-original-title=\"Popover\" data-html=\"true\" data-placement=\"bottom\" type=\"button\" class=\"btn btn-default\" aria-label=\"Left Align\">";
      newHTML += "<span class=\"glyphicon glyphicon-chevron-down\" aria-hidden=\"true\"></span></button>";
    
      //Creating new Element
      var trhtml = document.getElementById("table").insertRow();
      //add empty first empty column
      var tdhtml0 = document.createElement("td");
      trhtml.appendChild(tdhtml0);
      var tdhtml1 = document.createElement("td");
      tdhtml1.style = "text-align: center; vertical-align: middle;";
      tdhtml1.innerHTML = newHTML;
      trhtml.appendChild(tdhtml1);
    
    
    
      //Append newDiv to Popovercontent
      $("#btn" + id).popover({
        html: true,
        content: function(id) {
          return $("#newDiv" + id).html();
        }.bind(this, id)
      });
    
      id = id + 1;
    }
    <link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">
    <script src="//code.jquery.com/jquery-1.12.4.js"></script>
    <script src="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
    
    <table id="table" class="table">
      <tr>
        <th>Col 1</th>
        <th>Col 2</th>
      </tr>
      <tr>
        <td>
          <div id="div" style="display:none">
            <input type="checkbox">Label 1
            <br>
            <input type="checkbox">Label 2
          </div>
        </td>
        <td style="text-align: center; vertical-align: middle;">
          <button data-toggle="popover" id="btn1" data-original-title="Popover" data-html="true" data-placement="bottom" type="button" class="btn btn-default" aria-label="Left Align">
            <span class="glyphicon glyphicon-chevron-down" aria-hidden="true"></span>
          </button>
        </td>
      </tr>
    </table>
    
    <button onclick="addButton()">Add Row</button>