2

I am trying to add a class to an element depending on whether the user has clicked on a link. There is a similar question here but it is not working as I wanted it to be.

I created a component which has its own internal data object which has the property, isShownNavigation: false. So when a user clicks on the a I change isShownNavigation: true and expect my css class isClicked to be added. Alas that is not happening - isShownNavigation stays false in the component when I displayed it {{isShownNavigation}} but I can see in the console that my method is working when clicked.

I imported my header component to the App. Code is below.

Header Component

<template>
<header class="header">
  <a 
    href="#"
    v-bind:class="{isClicked: isShowNavigation}"
    v-on:click="showNavigation">
    Click
  </a>
</header>
</template>

<script>
export default {
  name: 'header-component',
  methods: {
    showNavigation: () => {
      this.isShowNavigation = !this.isShowNavigation
    }
  },
  data: () => {
    return {
      isShowNavigation: false
    }
  }
}
</script>

Application

<template>
  <div id="app">
    <header-component></header-component>
  </div>
</template>

<script>
import HeaderComponent from './components/Header.vue'
export default {
  name: 'app',
  components: {
    'header-component': HeaderComponent
  }
}
</script>

I am using the pwa template from https://github.com/vuejs-templates/pwa.

Thanks.

Bert
  • 80,741
  • 17
  • 199
  • 164
Browsing
  • 37
  • 6

1 Answers1

2

Don't use fat arrow functions to define your methods, data, computed, etc. When you do, this will not be bound to the Vue. Try

export default {
  name: 'header-component',
  methods: {
    showNavigation(){
      this.isShowNavigation = !this.isShowNavigation
    }
  },
  data(){
    return {
      isShowNavigation: false
    }
  }
}

See VueJS: why is “this” undefined? In this case, you could also really just get rid of the showNavigation method and set that value directly in your template if you wanted to.

<a 
  href="#"
  v-bind:class="{isClicked: isShowNavigation}"
  v-on:click="isShowNavigation = true">
  Click
</a>

Finally, if/when you end up with more than one link in your header, you will want to have a clicked property associated with each link, or an active link property instead of one global clicked property.

Bert
  • 80,741
  • 17
  • 199
  • 164
  • Thanks it works perfectly. I have a navigation `div` to which I will be adding the class and not on the `a`. I have used `a` for simplicity. There is a good answer https://forum.vuejs.org/t/how-to-make-a-component-with-menu-item-changing-css-to-active-when-clicked/3235 on how to do it if you want to add styles to different navigation links. It is an interesting approach. – Browsing Jun 03 '17 at 14:34
  • You can definitely rely on answers from @LinusBorg :) He is a core member of the Vue team. He answers questions here as well. – Bert Jun 03 '17 at 14:37