16

i'm using ajax load to get some content on my page. I'm working with bootstrap 3 and bootstrap toggle. when the content is loaded the bootstrap 3 content works fine (you can clearly see the panel panel-primary). But the bootstrap toggle content doesn't get loaded (you can just see some checkboxes). Does annyone know how to get this working? Or should i look out to some other toggle switches? Ifso which ones?

EDIT: i haven't tested out event binding yet because i cant get the bootstrap toggle css to work on the ajax loaded code. Event binding has nothing to do with the css right?

  1. Scripts used by the main html code (the one with ajax load)
  2. Main html code
  3. code being loaded into a div by the main html code

<!-- jQuery -->
<script src="../bower_components/jquery/dist/jquery.min.js"></script>

<!-- Bootstrap Core JavaScript -->
<script src="../bower_components/bootstrap/dist/js/bootstrap.min.js"></script>

 <!-- Bootstrap Toggle JavaScript -->
<script src="../bower_components/bootstrap-toggle-master/js/bootstrap-toggle.min.js"></script>

<!-- Metis Menu Plugin JavaScript -->
<script src="../bower_components/metisMenu/dist/metisMenu.js"></script>

<!-- Custom Theme JavaScript -->
<script src="../dist/js/sb-admin-2.js"></script>

<!-- Custom Domotica JavaScript -->
<script> $(document).ready(function(){
        // Set trigger and container variables
        var trigger = $('#side-menu li ul li a'),
        container = $('#page-wrapper');
        
        // Fire on click
        trigger.on('click', function(){
            
          // Set $this for re-use. Set target from data attribute
          var $this = $(this),
            target = $this.data('target');       
            alert("target: " + target)
          // Load target page into container
          container.load(target + '.html', function (response, status, xhr) {});
          // Stop normal link behavior
          return false;
        });
      });
</script>
<!DOCTYPE html>
<html lang="en">

<head>

  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="description" content="Home automation web page">
  <meta name="author" content="">

  <title>Home</title>

  <!-- Bootstrap Core CSS -->
  <link href="../bower_components/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">

  <!-- Bootstrap toggle -->
  <link href="../bower_components/bootstrap-toggle-master/css/bootstrap-toggle.min.css" rel="stylesheet">

  <!-- MetisMenu CSS -->
  <link href="../bower_components/metisMenu/dist/metisMenu.min.css" rel="stylesheet">

  <!-- Custom CSS -->
  <link href="../dist/css/sb-admin-2.css" rel="stylesheet">

  <!-- Custom Fonts -->
  <link href="../bower_components/font-awesome/css/font-awesome.min.css" rel="stylesheet" type="text/css">

  <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
  <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
  <!--[if lt IE 9]>
        <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
        <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
        <![endif]-->

</head>

<body>

  <div id="wrapper">

    <!-- Navigation -->
    <nav class="navbar navbar-default navbar-static-top" role="navigation" style="margin-bottom: 0">
      <div class="navbar-header">
        <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
          <span class="sr-only">Toggle navigation</span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
        </button>
        <a class="navbar-brand" href="index.html">Home</a>
      </div>
      <!-- /.navbar-header -->

      <ul class="nav navbar-top-links navbar-right">


        <li class="dropdown">
          <a class="dropdown-toggle" data-toggle="dropdown" href="#">
            <i class="fa fa-bell fa-fw"></i>  <i class="fa fa-caret-down"></i>
          </a>
          <ul class="dropdown-menu dropdown-alerts">
            <li>
              <a href="#">
                <div>
                  <i class="fa fa-comment fa-fw"></i> Failure
                  <span class="pull-right text-muted small">No respons from Controller 1</span>
                </div>
              </a>
            </li>

          </ul>
          <!-- /.dropdown-alerts -->
        </li>
        <!-- /.dropdown -->
        <li class="dropdown">
          <a class="dropdown-toggle" data-toggle="dropdown" href="#">
            <i class="fa fa-gear fa-fw"></i>
          </a>
          <!-- /.dropdown-user -->
        </li>
        <!-- /.dropdown -->
        <li class="dropdown">
          <a class="dropdown-toggle" data-toggle="dropdown" href="#">
            <i class="fa fa-sign-out fa-fw"></i> 
          </a>
        </li>
        <!-- /.dropdown -->
      </ul>
      <!-- /.navbar-top-links -->

      <div class="navbar-default sidebar" role="navigation">
        <div class="sidebar-nav navbar-collapse">
          <ul class="nav" id="side-menu">
            <li>
              <a href="index"><i class="glyphicon glyphicon-home"></i> House<span class="fa arrow"></span></a>
              <ul class="nav nav-second-level">
                <li>
                  <a href="#">Weather</a>
                </li>
                <li>
                  <a href="#">Energy</a>
                </li>
                <li>
                  <a href="#">Water</a>
                </li>
              </ul>
            </li>
            <li>
              <a href="#"><i class="glyphicon glyphicon-star"></i> 1st floor<span class="fa arrow"></span></a>
              <ul class="nav nav-second-level" id="side-menu2">
                <li>
                  <a href="#" data-target="index">Hallway</a>
                </li>
                <li>
                  <a href="#">Main bedroom</a>
                </li>
              </ul>
              <!-- /.nav-second-level -->
            </li>
            <li>
              <a href="#"><i class="glyphicon glyphicon-star"></i> main floor<span class="fa arrow"></span></a>
              <ul class="nav nav-second-level">
                <li>
                  <a href="#">Kitchen</a>
                </li>
                <li>
                  <a href="#">Living room</a>
                </li>
                <li>
                  <a href="#">Garage</a>
                </li>
              </ul>
              <!-- /.nav-second-level -->
            </li>
            <li>
              <a href="#"><i class="glyphicon glyphicon-star"></i> Basement</a> 
              <!-- /.nav-second-level -->
            </li>
            <li>
              <a href="#"><i class="glyphicon glyphicon-tree-deciduous"></i> Garden</a> 
              <!-- /.nav-second-level -->
            </li>
          </ul>
        </div>
        <!-- /.sidebar-collapse -->
      </div>
      <!-- /.navbar-static-side -->
    </nav>

    <div id="page-wrapper">

    </div>
    <!-- /#page-wrapper -->

  </div>
  <!-- /#wrapper -->
</body>

</html>
    <div class="panel panel-primary" id="switchespanel">
          <div class="panel-heading">
            <h3 class="panel-title">Switches</h3>
        </div>
        <div class="panel-body">
            <table class="table">
                <tr>
                    <th>Location</th>
                    <th>State</th>
                </tr>
                <tr>                
                <td>Testswitch0</td>
                    <td>
                        <label>
                            <input type="checkbox" data-toggle="toggle" data-onstyle="success" id="S0" data-size="mini">
                        </label>
                    </td>                 
                </tr>   
            </table>
        </div>
    </div>
Michvw
  • 329
  • 1
  • 4
  • 12
  • 1
    Try `$(document).on('click', '#side-menu li ul li a', function(){ });` . Note that `document` should really be another element that is closer to the target elements in the hierarchy – Wesley Smith Sep 15 '15 at 12:50
  • possible duplicate of [Event binding on dynamically created elements?](http://stackoverflow.com/questions/203198/event-binding-on-dynamically-created-elements) – Wesley Smith Sep 15 '15 at 12:52
  • 1
    The Css doesn't even get loaded to the checkbox, its not just event binding, I tried you're suggested solution without any succes. – Michvw Sep 15 '15 at 13:16
  • I got similar problems some time ago, boostrap css was incorrect rendered on inserted chunks of html loaded by ajax, or generated as strings in javascript code. First check the quality of generated (html open closed tags) second the problem what I got into back then were the missing spaces from string transformed to html, generate string appended to containers most be like "
    text
    " not like "
    text
    ", don't ask me why...
    – SilentTremor Sep 15 '15 at 13:32
  • Which version of bootstrap are you using? – Wesley Smith Sep 15 '15 at 13:34
  • BTW, your html is not valid, you cant have `
    ` wrapping `td` elements the way you do, you need a nested table there not a div, and you also use the `id="checkbox"` multiple times which is not valid. Just a heads up
    – Wesley Smith Sep 15 '15 at 13:39
  • bootstrap 3 i think, i'm using this template: http://startbootstrap.com/template-overviews/sb-admin-2/ I edited the html code. Note that it is the bootstrap toggle css that isn't loading (that's a different file) the bootstrap 3 css is doing fine, thats the strange thing – Michvw Sep 15 '15 at 13:52

2 Answers2

16

Make sure that you are loading both the bootstrap-toggle js file and css file properly. Specifically check that they are in the location your links point to, or even use the cdn versions listed below:

<link href="https://gitcdn.github.io/bootstrap-toggle/2.2.0/css/bootstrap-toggle.min.css" rel="stylesheet">
<script src="https://gitcdn.github.io/bootstrap-toggle/2.2.0/js/bootstrap-toggle.min.js"></script>

Your paths must be wrong or you forgot to include the js file altogether, and you should see a warning about this in your console because otherwise the code works fine.

Regarding dynamically loaded content.

The first elements work because, after the html first loads, bootstrap-toggle.min.js looks for any elements that have the attribute data-toggle="toggle" and calls .bootstrapToggle() on them applying the plugin. This only happens when the page loads.

If you later add more toggles, you'll need to initialize them yourself via .bootstrapToggle(). Iv'e updated the example below to simulate adding toggles dynamically and explain the approach I would take to do that. See the comments in the code for more details.

      // timeout to simulate ajax
setTimeout(function(){ 
   // add an element dynamically,
  $('.table').append('<tr><td>Testswitch0</td><td><label><input type="checkbox" data-toggle="toggle" data-onstyle="success" id="S2" data-size="mini"></label></td></tr>');
    
    // now that we have dynamically loaded elements
    // we need to initialize any toggles that were added
    // you shouldn't re-initialize any toggles already present
    // but we also do want to have to figure out how to find the ones we added
    // instead, we'll destroy all toggles and recreate all new ones
    $("[data-toggle='toggle']").bootstrapToggle('destroy')                 
    $("[data-toggle='toggle']").bootstrapToggle();
  
}, 2000)
      
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<link href="https://gitcdn.github.io/bootstrap-toggle/2.2.0/css/bootstrap-toggle.min.css" rel="stylesheet">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script src="https://gitcdn.github.io/bootstrap-toggle/2.2.0/js/bootstrap-toggle.min.js"></script>
<div class="panel panel-primary" id="switchespanel">
  <div class="panel-heading">
    <h3 class="panel-title">Switches</h3>
  </div>
  <div class="panel-body">
    <table class="table">
      <tr>
        <th>Location</th>
        <th>State</th>
      </tr>
      <tr>
        <td>Testswitch0</td>
        <td><label>
            <input type="checkbox" data-toggle="toggle" data-onstyle="success" id="S0" data-size="mini">
          </label></td>
      </tr>
      <tr>
        <td>Testswitch0</td>
        <td><label>
            <input type="checkbox" data-toggle="toggle" data-onstyle="success" id="S1" data-size="mini">
          </label></td>
      </tr>
    </table>
  </div>
</div>
Wesley Smith
  • 19,401
  • 22
  • 85
  • 133
  • thanks, using you're code does indeed render the css of the bootstrap toggles perfectly. It does mess with the rest of my html page but that stops by removing the bootstrap link and script (maybe because they're loaded twice like this?). anyway before and after the delete of the bootstrap link and script the switches don't toggle but that's probably an event binding problem, no? – Michvw Sep 15 '15 at 14:49
  • Your theme uses a css file that overrides the default bootstrap css. To do that they load a css file after the bootstrap css file. If you re-add the bootstrap css after that file it negates the changes and is why doing so mucks with your theme. You don't need to include bootstrap again. The main thing to take from my example (besides the right url) is the order in which the files are loaded, make sure your load order is the same regardless of where you get the files – Wesley Smith Sep 15 '15 at 14:56
  • Thanks for that lesson! Do you have any idea why the toggle isn't working after ajax load? – Michvw Sep 15 '15 at 15:10
  • @Michvw No problem, see my update for dynamic content info – Wesley Smith Sep 15 '15 at 15:49
3

The best solution that worked:

1- Load Jquery before bootstrap. Here Jquery first, Ajax second and bootstrap in the end.

    <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/gh/gitbrent/bootstrap4-toggle@3.6.1/js/bootstrap4-toggle.min.js"></script>

2- Call bootstrapToggle on ajax complete:

    $(document).ajaxComplete(function() {
        $('input[type=checkbox][data-toggle^=toggle]').bootstrapToggle();
    });

3- Note: Call your custom script jquery at the end

matthias_h
  • 11,356
  • 9
  • 22
  • 40
Talha Shahab
  • 189
  • 1
  • 5