M.Koops
M.Koops

Reputation: 155

How can I make navbar items with vue-router-links to toggle the navbar?

I have a nav-bar that works fine. Except for the fact that it does not close when an item is clicked. It does close when I click anywhere else in the window.

I work in laravel 8 and vue-3, have bootstrap-5 installed.

The navbar:


<template>
<div class="container-fluid navbar-custom-header">
<a class="close-navbar-toggler collapsed" data-bs-toggle="collapse" data-bs-target="#mySideBar" aria-controls="mySideBar" aria-expanded="false" aria-label="Toggle navigation">
</a>
   <nav class='navbar-custom navbar-dark fixed-top' >
       <div class="row " style="vertical-align:center">
           <div class="col-2">
               <button  class="openbtn dropdown-toggle" data-bs-toggle="collapse"  data-bs-target="#mySideBar">&#9776;</button>
           </div>    
           
           <div class="col-3">
               <a href="#" class="navbar-brand">Cards</a>
           </div> 
           <div class="col-3" v-if="!loggedIn">
               <router-link to="/login"> Login </router-link>
           </div>
           <div class="col-3" v-if="loggedIn">
               <router-link to="/logout"> Logout </router-link>
           </div>
             
       </div>
   </nav>
</div>
<div class="navbar-custom-container" style="z-index:10">
   <nav id="mySideBar" class="collapse navbar-custom navbar-collapse">
       <div class="navbar-custom-items">    
           <ul class="nav navbar-nav">
               <br>
               <br>
               <li class="nav-item"><router-link to="/memory" class="nav-link"> MemoryGame </router-link></li>
               <br>
               <li><router-link to="/cards" > Manage Cards </router-link></li>
               <br>
               <li><router-link to="/aanmelden"> Nieuwe Speler aanmelden </router-link></li>
               <br>
               <li><router-link to="/game"> Game spelen </router-link></li>
               <br>
               <li><router-link to="/game/admin"> GameAdmin </router-link></li>
           </ul>
       </div>
   </nav>
</div>
              
</template>

<script>


export default {
computed: {
   loggedIn() {
       return this.$store.getters.loggedIn
   }
}
   
 
} 

</script>


and the accompanying css:

// Variables
@import 'variables';

// Bootstrap
@import '~bootstrap/scss/bootstrap';


.close-navbar-toggler{
    position:absolute;
    top:0;
    left:0;
    height:100%;
    width:100%;
    z-index:1;
    cursor:pointer;
  }

  .close-navbar-toggler.collapsed{
    z-index:-1;
  }
  
.navbar-custom-header {
    background-color: rgb(5, 4, 71);
    color:rgb(245, 209, 8);
    margin:auto;

}
.navbar-custom-container {
    display:flex;
    justify-content:flex-start;
    position:absolute;
    //padding:0px 12px;

}

.navbar-header {
    background-color: rgb(5, 4, 71);
}

.navbar-custom {
    background-color: rgb(17, 15, 172);
    color:yellow;
    padding:12px -12px;
}

.navbar-toggler-icon {
    vertical-align:middle;
    text-align:left;
}

.navbar-custom-items > a:link {
    color:black;   
}
.navbar-custom-items > a:active {
    color:rgb(73, 7, 7);   
}
.navbar-custom-items > a:hover {
    color:rgb(138, 59, 241);   
}

I realize that I do not fully understand how Bootstrap catches the collapse-command. Can anyone explain?

Upvotes: 0

Views: 2200

Answers (2)

Santironhacker
Santironhacker

Reputation: 1004

I would like to add further explanation to the answer of @Nechoj and provide another strategy for solving the issue. Because using v-model over the <b-collapse> or <div>, will get you a warning from Vue: enter image description here

In Bootstrap 4 and 5, the collapse class is the key for toggling your Navbar. Therefore, as @Nechoj suggests the toggling mechanism can be achieved with:

<script setup>
    import {ref} from 'vue';

    const visible = ref(false)
    const toggleVisible = () => {
        visible.value = !visible.value
    }
</script>

And in the template:

  1. Bind the container element you wish to collapse with :class="visible ? null : 'collapsed'"
  2. Add the method @click="toggleVisible" to the <router-link> elements and the <button> that aims to toggle the NavBar.
<div class="container-fluid">
    <button
        class="navbar-toggler"
        type="button"
        @click="toggleVisible"
        :aria-expanded="visible ? 'true' : 'false'"
        aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
    </button>

    <b-collapse class="navbar-collapse" :class="visible ? null : 'collapsed'">
        <ul class="navbar-nav me-auto mb-2 mb-lg-0">
            <li class="nav-item">
                <router-link
                    class="nav-link"
                    :to="{ name: 'home' }"
                    @click="toggleVisible">
                    home
                </router-link>
            </li>
            <li class="nav-item">
                <router-link class="nav-link" :to="{ name: 'page1' }" @click="toggleVisible">
                    page1
                </router-link>
            </li>
        </ul>
    </b-collapse>
</div>

Please note that when following this strategy that collapses the content using a method + CSS, the data-bs-toggle and data-bs-target attributes related to Bootstrap should be removed. If you try to add data-bs-toggle and data-bs-target attributes to the <router-link> elements that already have the @click method you will have weird behaviors. This is because the Navbar is Bootstrap is not conceived to have the navigations links toggle the visibility of the navbar itself.

Upvotes: 0

Nechoj
Nechoj

Reputation: 1582

In vue3you would have a component that represents the nav menu as a template. Then, the component would look like this (using bootstrap-vue-3 components such as b-collapse, but you can use div tags as well):

<template>
  <nav class="navbar navbar-expand-md navbar-dark bg-dark">
    <div class="container-fluid">
      <button class="navbar-toggler" type="button"
              :class="visible ? null : 'collapsed'"
              :aria-expanded="visible ? 'true' : 'false'"
              @click="visible = !visible"
              aria-controls="navbarSupportedContent"
              aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
      </button>
      <b-collapse class="collapse navbar-collapse" id="navbarSupportedContent" v-model="visible">
        <ul class="navbar-nav me-auto mb-2 mb-lg-0">
          <li class="nav-item">
            <router-link class="nav-link" :to="{name: 'home'}" @click="visible = !visible">
             home
            </router-link>
          </li>
          <li class="nav-item">
            <router-link class="nav-link" :to="{name: 'page1'}" @click="visible = !visible">
             page1
            </router-link>
          </li>
        </ul>
      </b-collapse>
    </div>
  </nav>
</template>

<script setup>
import {ref} from 'vue'
const visible = ref(false)
</script>

In the template example you can see that clicking on the navbar-toggler or on the links, the visible attribute of the components gets toggled. And the navbarSupportedContentelement is visible, depending on the value of visible (v-model="visible"). If you do not use bootstrap-vue-3, then you would use v-show="visible" inside your div to toggle it.

Upvotes: 1

Related Questions