How can I filter my bootstrap 4 navbar links with a search bar?

filtering, javascript, jquery, search, twitter-bootstrap

Solution

Okay, I think i've figured it out on my own (with a little help from this post for a case insensitive filter).

1) I updated the links by wrapping them in a `div with id #link-content`, to separate my filter from the home and search input.

2) I added the case insensitive method referenced above

My HTML:

   <ul class="sidebar-nav navbar-nav">
      <li class="nav-item active">
         <a class="nav-link" href="#"><i class="fa fa-fw fa-home"></i> Home</a>
      </li>
      <li class="nav-item">
         <label for="nav-search" class="col-2 col-form-label sr-only">Search links</label>
         <div class="col p-2">
            <input class="form-control form-control-sm search-filter" type="search" id="nav-search" placeholder="Search for tools">
         </div>
      </li>
 <div id="link-content"><!-- added this to wrap the links-->     
      <li class="nav-item">
         <span class="navbar-brand">Popular tools</span>
      </li>
      <li class="nav-item filter">
         <a class="nav-link" href="#"><i class="fa fa-fw fa-calculator"></i> Calculator</a>
      </li>
      <li class="nav-item  filter">
         <a class="nav-link" href="#"><i class="fa fa-fw fa-battery-3"></i> Battery </a>
      </li>
      <li class="nav-item  filter">
         <a class="nav-link" href="#"><i class="fa fa-fw fa-database"></i> Pancake Batter</a>
      </li>

      <li class="nav-item  filter">
         <a class="nav-link" href="#"><i class="fa fa-fw fa-clock-o"></i> Marzipan</a>
      </li>
      <li class="nav-item  filter">
         <a class="nav-link" href="#"><i class="fa fa-fw fa-tags"></i> Cakes and Muffins</a>
      </li>
      <li class="nav-item  filter">
         <span class="navbar-brand">Categories</span>
      </li>
      <li class="nav-item ">
         <a class="nav-link nav-link-collapse collapsed" data-toggle="collapse" href="#collapseComponents"><i class="fa fa-fw fa-flask"></i> Cars</a>
         <ul class="sidebar-second-level collapse" id="collapseComponents">
            <li>
               <a class="nav-link-collapse collapsed" data-toggle="collapse" href="#collapseMulti2">American</a>
               <ul class="sidebar-third-level collapse" id="collapseMulti2">
                  <li>
                     <a href="#">Ford</a>
                  </li>
                  <li>
                     <a href="#">GMC</a>
                  </li>
               </ul>
            </li>
            <li>
               <a class="nav-link-collapse collapsed" data-toggle="collapse" href="#collapseMulti3">European</a>
               <ul class="sidebar-third-level collapse" id="collapseMulti3">
                  <li>
                     <a href="#">BMW</a>
                  </li>
                  <li>
                     <a href="#">Audi</a>
                  </li>
               </ul>
            </li>
         </ul>
      </li>
      </div>
   </ul>

My updated code:

// Case insensitive method for filter
jQuery.expr[':'].casecontains = (a, b, c) => jQuery(a).text().toUpperCase().indexOf(c[3].toUpperCase()) >= 0;

$('.search-filter').on('keyup', function () {
            var input = $('.search-filter').val();
                        console.log('input: '+input);
            if (input.length != 0) { 
            // first hide the div #link-content lists from view
            $('#link-content li').hide();
            // but secretly unhide the collapsed links
            // using .show, so the nested uls can be viewed
            $('#link-content li.nav-item ul').show();
            // then filter in the matching links only
            $('#link-content li:casecontains("'+input+'")').show();
            } else {
            // secretly unhide the collapsed links
            $('#link-content li.nav-item ul').hide();  
            // if search is empty, show the div and reset columns
            $('#link-content li').show();
            }
        });

Here is a fiddle with the working example that opens any hidden links (collapsed class in boostrap 4).

Problem

I'm transitioning my old website using Bootstrap 4, so it's definitely been a process of learning. I've got the site layout working fine, but I realize that my left-sided vertical nav bar has a lot of links. Many of these grouped in collapsed nests. I think it would be nice to add a search bar at the top of my nav so that I can filter the links based on partial strings entered in the search bar. This works for links that are not hiding inside a hidden div (or `class=collapsed` boostrap 4 ul). I'd appreciate assistance in modifying my code to show filtered results that include any links hiding inside the collapsed ul? Here's a fiddle ``` $('.search-filter').on('keyup', function() { var input = $('.search-filter').val(); var filter = input.toLowerCase(); if (filter.length == 0) { // show all if filter is empty $('a').each(function() { $(this).show(); // show links }); return; } else { $('a').removeClass('collapsed'); $('a').each(function() { $(this).hide(); // hide all links once search is begun }); $('a:contains("' + filter + '")').each(function() { $(this).removeClass('collapsed'); // remove bootstrap 4 collapsed class designation $(this).show(); // show only matched links to search string? }); } }); ``` ``` @import url('https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css'); .navbar-nav.sidebar-nav { position: absolute; left: 0; top: 0; margin-top: 56px; padding-bottom: 56px; height: 100vh; background: #292b2c; -webkit-flex-direction: column; -ms-flex-direction: column; flex-direction: column; overflow: auto; } .navbar-brand { display: inline-block; padding-top: .25rem; padding-bottom: .25rem; margin-right: 1rem; font-size: 1.25rem; line-height: inherit; white-space: nowrap; color: #fff; } .navbar-nav .nav-link { color: rgba(255, 255, 255, .5); } ``` ``` <div id="link-content"> <ul class="sidebar-nav navbar-nav"> <li class="nav-item active"> <a class="nav-link" href="#"><i class="fa fa-fw fa-home"></i> Home</a> </li> <li class="nav-item"> <label for="nav-search" class="col-2 col-form-label sr-only">Search links</label> <div class="col p-2"> <input class="form-control form-control-sm search-filter" type="search" id="nav-search" placeholder="Search for tools"> </div> </li> <li class="nav-item"> <span class="navbar-brand">Popular tools</span> </li> <li class="nav-item"> <a class="nav-link" href="#"><i class="fa fa-fw fa-calculator"></i> Calculator</a> </li> <li class="nav-item"> <a class="nav-link" href="#"><i class="fa fa-fw fa-battery-3"></i> Battery </a> </li> <li class="nav-item"> <a class="nav-link" href="#"><i class="fa fa-fw fa-database"></i> Pancake Batter</a> </li> <li class="nav-item"> <a class="nav-link" href="#"><i class="fa fa-fw fa-clock-o"></i> Marzipan</a> </li> <li class="nav-item"> <a class="nav-link" href="#"><i class="fa fa-fw fa-tags"></i> Cakes and Muffins</a> </li> <li class="nav-item"> <span class="navbar-brand">Categories</span> </li> <li class="nav-item"> <a class="nav-link nav-link-collapse collapsed" data-toggle="collapse" href="#collapseComponents"><i class="fa fa-fw fa-flask"></i> Cars</a> <ul class="sidebar-second-level collapse" id="collapseComponents"> <li> <a class="nav-link-collapse collapsed" data-toggle="collapse" href="#collapseMulti2">American</a> <ul class="sidebar-third-level collapse" id="collapseMulti2"> <li> <a href="#">Ford</a> </li> <li> <a href="#">GMC</a> </li> </ul> </li> <li> <a class="nav-link-collapse collapsed" data-toggle="collapse" href="#collapseMulti3">European</a> <ul class="sidebar-third-level collapse" id="collapseMulti3"> <li> <a href="#">BMW</a> </li> <li> <a href="#">Audi</a> </li> </ul> </li> </ul> </li> </ul> </div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js"></script> ```

Original source

Related problems