Bootstrap 4 Persistent Tabs

by Justin Williamson

HTML

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<div class="container my-5">

  <div class="row mb-3">
    <div class="col">
      <button class="btn btn-danger" onclick="location.reload(true)">
        Reload Page
      </button>
    </div>
  </div>
  
  <div class="row">  
    <div class="col">
      <div class="card">
        <div class="card-body text-center">
          <h5 class="card-title">
            My List Group
          </h5>
        </div>
        <div class="list-group list-group-flush">
          <a href="#item1" id="item1-list" class="list-group-item list-group-item-action" data-toggle="list" role="tab" aria-controls="Item 1">
            <div>
              <h6 class="d-inline">Item 1</h6>
            </div>
          </a>
          <a href="#item2" id="item2-list" class="list-group-item list-group-item-action" data-toggle="list" role="tab" aria-controls="Item 2">
            <div>
              <h6 class="d-inline">Item 2</h6>
            </div>
          </a>
          <a href="#item3" id="item3-list" class="list-group-item list-group-item-action" data-toggle="list" role="tab" aria-controls="Item 3">
            <div>
              <h6 class="d-inline">Item 3</h6>
            </div>
          </a>
        </div>
      </div>
    </div>
    <div class="col">
      <div class="tab-content">
        <div class="tab-pane fade" id="item1" role="tabpanel" aria-labelledby="item1-list">
          Item 1 Content
        </div>
        <div class="tab-pane fade" id="item2" role="tabpanel" aria-labelledby="item2-list">
          Item 2 Content
        </div>
        <div class="tab-pane fade" id="item3" role="tabpanel" aria-labelledby="item3-list">
          Item 3 Content
        </div>
      </div>
    </div>
  </div>
</div>

JavaScript

/**
 * Toggle the panel based on the current hash
 */
function togglePanelBasedOnHash(e) {
  if (e && e.target === window) return;
  const hash = $(`#${location.hash.replace(/#/g, '')}-list`).length ? location.hash.replace(/#/g, '') : 'item1';
  $(`#${hash || 'item1'}-list`).trigger('click');
}
$(window).on('hashchange', togglePanelBasedOnHash);
togglePanelBasedOnHash();

/**
 * Update the hash when changing tab panels (this persists the currently open tab)
 */
$('a[data-toggle="list"]').on('show.bs.tab', function () {
  location.hash = $(this).attr('href');
});