Search code examples
vue.jsnavbarrouterlink

Navigation bar (Mobile view) doesn't close after click - Vuejs


When I click nav link on navbar it does not collapse. Vue version 2.6.10.

    <template>
  <div class="nav-wrapper">
    <nav>
      <ul>
        <li v-for="(route, index) in routings" :key="index">
          <router-link :to="route.url">{{route.name}}</router-link>
        </li>
        <li>
          <a href="https://blog.inquest.io/" target="_blank">Blog</a>
        </li>
        <li class="visible-xs">
          <Button v-if="!isLoggedIn" :label="loginButtonLabel" :isFilled="true" :action="goToLogin"/>
          <UserWidget v-else :email="setFirstName" :title="'administrator'" :isUserMenu="true" :action="gotoDashboard"/>
        </li>
      </ul>
    </nav>
  </div>
</template>

This is the navbar what i talk about

This is the header part of the code. When click on the hamburger icon class 'mobile-menu-wrapper visible-xs' this will change to 'mobile-menu-wrapper visible-xs expanded'. There for I think it will be change to previous class its solve the matter. Please advise me to find the issue.

 <template>
      <div class="header-wrapper">
        <div class="header-container container">
          <Logo/>
          <Nav class="hidden-xs" :routings="routings"/>
          <Button v-if="!isLoggedIn" class="hidden-xs" :label="isLoggedIn ? 'Console' : 'Login / Sign-up'" :isFilled="true" :action="goToLogin"/>
          <UserWidget class="hidden-xs" v-if="isLoggedIn" :email="setFirstName" :title="'administrator'" :isUserMenu="true" :action="gotoDashboard"/>
          <div class="mobile-menu-icon-wrapper visible-xs" @click="getMobileMenu">
            <i v-if="isMenuExpanded" class="mobile-menu-icon close-icon"></i>
            <i v-if="!isMenuExpanded" class="mobile-menu-icon expand-icons"></i>
          </div>
          <div class="mobile-menu-wrapper visible-xs" :class="{'expanded': isMenuExpanded}">
            <div class="menu-overlay" @click="getMobileMenu"></div>
            <Nav :routings="routings" :eventBus="eventBus" :adminDetails="adminDetails" :isLoggedIn="isLoggedIn"/>
            <div class="mobile-menu-icon-wrapper" @click="getMobileMenu">
              <i v-if="isMenuExpanded" class="mobile-menu-icon close-icon"></i>
            </div>
          </div>
        </div>
      </div>
    </template>

Solution

  • Try to add an onclick event in your router link to close the navigation bar, I don't see the code that you're using to open/close the nav, but you can emit an event like this:

    Let's listen for the event closeNav in the parent component, by adding @closeNav in the Nav component:

    <template>
      <div class="header-wrapper">
        <div class="header-container container">
          <Logo/>
          <Nav class="hidden-xs" :routings="routings"/>
          <Button v-if="!isLoggedIn" class="hidden-xs" :label="isLoggedIn ? 'Console' : 'Login / Sign-up'" :isFilled="true" :action="goToLogin"/>
          <UserWidget class="hidden-xs" v-if="isLoggedIn" :email="setFirstName" :title="'administrator'" :isUserMenu="true" :action="gotoDashboard"/>
          <div class="mobile-menu-icon-wrapper visible-xs" @click="getMobileMenu">
            <i v-if="isMenuExpanded" class="mobile-menu-icon close-icon"></i>
            <i v-if="!isMenuExpanded" class="mobile-menu-icon expand-icons"></i>
          </div>
          <div class="mobile-menu-wrapper visible-xs" :class="{'expanded': isMenuExpanded}">
            <div class="menu-overlay" @click="getMobileMenu"></div>
            
            <!-- here is part of the magic -->
            <!-- alternative one, update isMenuExpanded directly -->
            <Nav :routings="routings" :eventBus="eventBus" :adminDetails="adminDetails" :isLoggedIn="isLoggedIn" @closeNav="isMenuExpanded = false"/>
    
            <!-- alternative two, update isMenuExpanded using the closeNavBar method -->
            <!--<Nav :routings="routings" :eventBus="eventBus" :adminDetails="adminDetails" :isLoggedIn="isLoggedIn" @closeNav="closeNavBar"/> -->
            
            <div class="mobile-menu-icon-wrapper" @click="getMobileMenu">
              <i v-if="isMenuExpanded" class="mobile-menu-icon close-icon"></i>
            </div>
          </div>
        </div>
      </div>
    </template>
    <script>
    export default {
      ...
      methods: {
        // alternative using method
        closeNavBar() {
          this.isMenuExpanded = false;
        }
      }
      ...
    }
    </script>
    

    The navbar component will emit the event once the user clicks on any router-link (you can add the event in any other link or button)

    <template>
      <div class="nav-wrapper">
        <nav>
          <ul>
            <li v-for="(route, index) in routings" :key="index">
    
              <!-- emit the event to close the navBar -->
              <!-- emit directly in the tag -->
              <router-link :to="route.url" @click="$emit('closeNav')">{{route.name}}</router-link>
    
              <!-- emit by using a method -->
              <!--<router-link :to="route.url" @click="closeNavBarFromChild">{{route.name}}</router-link>-->
            </li>
            <li>
              <a href="https://blog.inquest.io/" target="_blank">Blog</a>
            </li>
            <li class="visible-xs">
              <Button v-if="!isLoggedIn" :label="loginButtonLabel" :isFilled="true" :action="goToLogin"/>
              <UserWidget v-else :email="setFirstName" :title="'administrator'" :isUserMenu="true" :action="gotoDashboard"/>
            </li>
          </ul>
        </nav>
      </div>
    </template>
    <script>
      ...
      methods: {
        closeNavBarFromChild() {
          this.$emit('closeNav') // Emit the event that the parent is listening
        }
      }
      ...
    </script>
    

    I wrote two ways to use events, but they have the same effect.