Search code examples
javascripthtmltoggle

Maintain colllapse-state after refresh


In my Sidebar I included a collapse button to show/hide a form. Now I want to maintain the collapse-state when refreshing the page: If the form was un-collapsed before refreshing the page, it must stay like this after the refresh.

I think I need to use the localStrorage in JavaScript, but I actually don't know how to use this.

This is my HTML:

<!-- Sidebar -->
    <ul class="sidebar navbar-nav">
         <li class="nav-item active">
                  <a class="nav-link" data-toggle="collapse" href="#collapseExample" role="button" aria-expanded="false" aria-controls="collapseExample">
                      <i class="fa fa-filter"></i>
                      <span>Search Filter</span>
                  </a>
          </li>


 </ul>

<!-- Form -->
<div class="collapse" id="collapseExample">
<form>
......
</form>

I found some code only but it seems like it does not work for me..:

var shown = []

// On collapse
shown.remove($(this).attr('id'));
localStorage.setItem('shown', shown);

// On open
shown.push($(this).attr('id'));
localStorage.setItem('shown', shown);

// On page load
var shown = localStorage.getItem('shown');
for (var s in shown) {
    $('#collapseExample' + s).show(); 
}

Thanks for your help!


Solution

  • Here's a Bootstrap 4 collapse example that works. The main difference from the starter template is that I moved the jQuery import to the top of the file so that I could use the document.load function. I've added comments to the code but if anything's still not clear, keep asking questions. Note that I left the vanilla javascript answer for historical comments and in case it helps you, too.

    I used the starter page from here: https://getbootstrap.com/docs/4.0/getting-started/introduction/

    And the first collapse example from here: https://getbootstrap.com/docs/4.0/components/collapse/

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <!-- Required meta tags -->
        <meta charset="utf-8" />
        <meta
          name="viewport"
          content="width=device-width, initial-scale=1, shrink-to-fit=no"
        />
    
        <!-- Bootstrap CSS -->
        <link
          rel="stylesheet"
          href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
          integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
          crossorigin="anonymous"
        />
    
        <title>Hello, world!</title>
        <!-- jQuery -->
        <script
          src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
          integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
          crossorigin="anonymous"
        ></script>
        <script>
          $(function() {
            // store a reference to the collapse div so that 
            // we don't have to keep looking it up in the dom
            const collapseExample = $("#collapseExample");
    
            // register a callback function to the collapse div that
            // will be called every time the collapse is opened.
            collapseExample.on("shown.bs.collapse", function() {
                // since we know that that this function is called on
                // open, we'll set the localStorage value to "show" 
                localStorage.setItem("collapseExample", "show");
            });
    
            // register a callback function to the collapse div that
            // will be called every time the collapse is closed.
            collapseExample.on("hidden.bs.collapse", function() {
                // since we know that that this function is called on
                // open, we'll set the localStorage value to "hide" 
                localStorage.setItem("collapseExample", "hide");
            });
    
            // Since this function runs on page load (meaning only once), we can
            // check the value of localStorage from here and then call the
            // bootstrap collapse methods ourselves:
    
            // Check the value of the localStorage item
            const showExampleCollapse = localStorage.getItem("collapseExample");
    
            // Manipulate the collapse based on the value of the localStorage item.
            // Note that the value is determined by lines 36 or 44. If you change those,
            // then make sure to check that the comparison on the next line is still valid.
            if (showExampleCollapse === "show") {
                collapseExample.collapse("show");
            } else {
                collapseExample.collapse("hide");
            }
          });
        </script>
      </head>
      <body>
        <main>
          <p>
            <a
              class="btn btn-primary"
              data-toggle="collapse"
              href="#collapseExample"
              role="button"
              aria-expanded="false"
              aria-controls="collapseExample"
            >
              Link with href
            </a>
            <button
              class="btn btn-primary"
              type="button"
              data-toggle="collapse"
              data-target="#collapseExample"
              aria-expanded="false"
              aria-controls="collapseExample"
            >
              Button with data-target
            </button>
          </p>
          <div class="collapse" id="collapseExample">
            <div class="card card-body">
              Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus
              terry richardson ad squid. Nihil anim keffiyeh helvetica, craft beer
              labore wes anderson cred nesciunt sapiente ea proident.
            </div>
          </div>
        </main>
    
        <!-- Optional JavaScript -->
        <!-- Popper.js, then Bootstrap JS -->
        <script
          src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
          integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
          crossorigin="anonymous"
        ></script>
        <script
          src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
          integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
          crossorigin="anonymous"
        ></script>
      </body>
    </html>
    
    

    END BOOTSTRAP ANSWER

    BEGIN VANILLA JAVASCRIPT ANSWER

    Here's a basic, self-contained version of what you seem to be trying to do. It's not pretty, but hopefully, it's clear.

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
        <script>
        function getCollapsed() {
            const state = localStorage.getItem('collapsed');
            if(state === 'collapsed'){
                return true;
            }
            return false;
        }
        function getStatus(){
            const resultDiv = document.getElementById('result');
            const isCollapsed = getCollapsed();
            if(isCollapsed){
                resultDiv.innerHTML = "collapsed";
            }else{
                resultDiv.innerHTML = "un-collapsed";
            }
        }
        function toggleCollapse(){
            const isCollapsed = getCollapsed();
            if(isCollapsed){
                localStorage.setItem('collapsed', 'un-collapsed');
            }else{
                localStorage.setItem('collapsed', 'collapsed');
            }
            getStatus();
        }
        </script>
    </head>
    <body onload="getStatus()">
        <div>
            <button onclick="toggleCollapse()">Toggle Collapse</button>
        </div>
        <div id="result"></div>
    </body>
    </html>