ssherlock
ssherlock

Reputation: 119

Bootstrap 5 navbar not toggling in Vue3

This is a similar question to How can I make navbar items with vue-router-links to toggle the navbar? but I am not allowed to comment there, and the solution given doesn't work me anyway.

I am using Vue 3 and Bootstrap 5 and the following code works exactly as the standard Bootstrap code does i.e. toggling the hamburger menu opens and closes the menu but clicking a link does nothing (other than correctly route to the page being clicked, meaning user has to then tap hamburger menu again to close)

NavBar component:

    <template>
  <nav class="navbar navbar-dark bg-dark navbar-expand-sm">
    <div class="container-fluid">
        <router-link class="navbar-brand" to="/">Birch Farm</router-link> |
        <button class="navbar-toggler" type="button"  
          :class="visible ? null : 'collapsed'" 
          data-bs-toggle="collapse" 
          data-bs-target="#navContent" 
          aria-controls="navContent" 
          :aria-expanded="visible ? 'true' : 'false'"
          @click="visible = !visible" 
          aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navContent">
            <ul class="navbar-nav ms-auto mb-2 mb-lg-0">
              <li class="nav-item active">
                <router-link class="nav-link px-3" active-link="active" to="/" @click="visible = !visible">Home</router-link>
              </li>
              <li class="nav-item">
                <router-link class="nav-link px-3" to="/camping" @click="visible = !visible">Camping &amp; Caravanning</router-link>
              </li>       
              <li class="nav-item">
                <router-link class="nav-link px-3" to="/fishing" @click="visible = !visible">Cat Rough Fishery</router-link>
              </li>  
              <li class="nav-item">
                <router-link class="nav-link px-3" to="/contact" @click="visible = !visible">Contact Us</router-link>
              </li>  
            </ul>
        </div>
    </div>
  </nav>
</template>

<script setup>
  import {ref} from 'vue'
  const visible = ref(false);
</script>
<script>
export default {
  name: "NavBar",
  created() {},
  data() {},
  props: {},
  methods: {},
  components: {}
};
</script>

<style lang="scss" scoped></style>

Not having any of the 'visible' stuff works exactly the same way - this was added when trying the solution given in the above link.

Upvotes: 4

Views: 4129

Answers (9)

Santironhacker
Santironhacker

Reputation: 1004

In my case, I removed the data-bs-toggle and data-bs-target attributes from Bootstrap 4 and 5 because when using those on navigation links inside the section which is intended to be collapsed, then the navigation is blocked.

Therefore, like @Carol Skelly mentions, the toggling effect is achieved thanks to the collapse CSS class implemented by bootstap:

<div class="navbar-collapse" :class="!visible?'collapse':''" id="navContent">

And the only thing left is to add a method to trigger the collapse after clicking on a navigation link (as already done in the original code of the question):

<li class="nav-item">
    <router-link class="nav-link px-3" to="/camping" @click="visible = !visible">
        Camping &amp; Caravanning
    </router-link>
</li>

Those previous pieces work thanks to the variable contained in the script using Vue 3 Composition API:

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

Upvotes: 0

Robin
Robin

Reputation: 1

I had the same problem. I solved it by adding:

import * from 'bootstrap';

in the app.js file.

After that, it's working.

Upvotes: 0

Roberto Vaccaro
Roberto Vaccaro

Reputation: 1

<li class="nav-item mx-1">  
                        <NuxtLink class="btn nav-button nav-text" to="/eventi">
                            <span data-bs-target="#navbarSupportedContent" data-bs-toggle="collapse">Servizi</span>
                        </NuxtLink>       
                    </li>

I solved adding a span tag with data-bs-target="#navbarSupportedContent" and data-bs-toggle="collapse" around the name of the links (in my case they are NuxtLink but I think works either with Router-link)

Upvotes: 0

Craig van Tonder
Craig van Tonder

Reputation: 7687

I thought to share my workaround/solution for this specific issue.

Do not use the router-link component, rather trigger the navigation manually via the push method in vue-router by handling the click event in vue.

This allows for a "static" layout of the HTML so that you can preserve the functionality in Bootstap which allows for controlling the collapsing of the navbar via data attributes.

In order to trigger the active navigation style you can use class binding in vue and the route.name value from vue-router. It would also work with the path given slight modification.

Here is a basic example:

<script setup>
  import { useRouter, useRoute } from 'vue-router'
  const router = useRouter()
  const route = useRoute()
  const navigate = name => router.push({ name })
</script>
  
<template>
  <div class="container">
    <span class="navbar-brand">EXAMPLE NAVBAR</span>
    <button class="navbar-toggler"
            type="button"
            data-bs-toggle="collapse"
            data-bs-target="#navbarNavAltMarkup"
            aria-controls="navbarNavAltMarkup"
            aria-expanded="false"
            aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarNavAltMarkup">
      <div class="navbar-nav">
        <li class="nav-item">
          <span :class="['nav-link', route.name === 'camping' ? ' active' : '']"
                role="button"
                data-bs-toggle="collapse"
                data-bs-target="#navbarNavAltMarkup"
                @click="navigate('camping')">CAMPING</span>
        </li>
        <li class="nav-item">
          <span :class="['nav-link', route.name === 'fishing' ? ' active' : '']"
                role="button"
                data-bs-toggle="collapse"
                data-bs-target="#navbarNavAltMarkup"
                @click="navigate('fishing')">FISHING</span>
        </li>
      </div>
    </div>
  </div>
</template>
  

Upvotes: 0

Sam85
Sam85

Reputation: 179

I found a tweak in this other thread for Vue 3 / Bootstrap 5 / vue-router : How to hide collapsible Bootstrap navbar on click

Adding a simple span tag around menu label and inside li / routerling worked for me:

<div class="collapse navbar-collapse" id="navigation">
            <ul class="navbar-nav me-auto mb-2 mb-sm-0">
               <li class="nav-item">
                  <RouterLink class="nav-link" to="/"><span data-bs-target="#navigation" data-bs-toggle="collapse">Menu 1</span></RouterLink>
               </li>
               <li class="nav-item">
                  <RouterLink class="nav-link" to="/ventes.html"><span data-bs-target="#navigation" data-bs-toggle="collapse">Menu 2</span></RouterLink>
               </li>
</ul>

I hope it helps!

Upvotes: 0

Ilesanmi John
Ilesanmi John

Reputation: 256

I changed data-toggle to data-bs-toggle and data-target to data-bs-target and it worked.

My main.js(main entry file) has this

...
import "bootstrap/dist/css/bootstrap.min.css";
import "bootstrap";
...

Upvotes: 2

be able
be able

Reputation: 81

I had the same issue, bootstrap (5.1.3) and Vue (3.2.36). So I installed bootstrap-vue-3 (0.1.13) and use and to make it work. Also without "navbar-light bg-light) the hamburger icon didn't appear at first. Hope this helps.

<template>
<nav class="navbar navbar-expand-lg fixed-top navbar-light bg-light">
    <div class="container-fluid">
        <RouterLink class="navbar-brand" to="/">
            <img class="logo" src="../assets/svg/logo.svg" />
        </RouterLink>
        <b-button
            v-b-toggle.collapse-1
            variant="primary"
            class="navbar-toggler"
            type="button"
            data-bs-toggle="collapse"
            data-bs-target="#menuItems"
            aria-controls="menuItems"
            aria-expanded="false"
            aria-label="Toggle navigation"
        >
            <span class="navbar-toggler-icon"></span>
        </b-button>
        <b-collapse id="collapse-1" class="mt-2 collapse navbar-collapse">
            <ul class="navbar-nav me-auto mb-2 mb-lg-0">
                <li class="nav-item">
                    <RouterLink class="nav-link" to=" /">home </RouterLink>
                </li>
                <li class="nav-item">
                    <RouterLink class="nav-link" to=" /something"
                        >something
                    </RouterLink>
                </li>
                <li class="nav-item">
                    <RouterLink class="nav-link" to="/about"
                        >about
                    </RouterLink>
                </li>
            </ul>
            <form class="d-flex">
                <input
                    class="form-control me-2"
                    type="search"
                    placeholder="Search"
                    aria-label="Search"
                />
                <button class="btn btn-outline-success" type="submit">
                    Search
                </button>
            </form>
        </b-collapse>
    </div>
</nav>

Upvotes: 0

Carol Skelly
Carol Skelly

Reputation: 362760

"toggling the hamburger menu opens and closes the menu but clicking a link does nothing (other than correctly route to the page being clicked"

That's how the Bootstrap Navbar works. It doesn't collapse/hide automatically after clicking a link. Normally you'd have to do something like this to close the Navbar after clicking a link.

But when using Vue you would toggle the collapse class as needed on the navbar-collapse div using your visible value...

<div class="navbar-collapse" :class="!visible?'collapse':''" id="navContent">

Demo: https://codeply.com/p/lHTzN4amfe

Upvotes: 3

AhmedSHA256
AhmedSHA256

Reputation: 663

You have to follow this guide if you are using bootstrap via NPM. As long as I see, the way to use it is different in Angular or React, for example.

In addition to that, if you want to use bootstrap in your project and set it up the easiest way possible, is to use the CDN, I will show you how:

In your main layout, inside the head tag, put this:

<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">

And inside your body tag, this:

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>

Upvotes: 0

Related Questions