[Vuejs]-Change a property's value in one component from within another component

4๐Ÿ‘

As it says on @lukebearden answer you can use the emit event to pass true/false to the main App component on router-link click.

Assuming your Navigation component looks like below, you can do something like that:

#Navigation.vue
<template>
  <div>
      <router-link to="/home" @click.native="leftContent(true)">Home</router-link> - 
      <router-link to="/notes" @click.native="leftContent(false)">Notes</router-link>
  </div>
</template>

<script>
export default {
  methods: {
    leftContent(value) {
      this.$emit('left-content', value)
    }
  }
}
</script>

And in your main App you listen the emit on Navigation:

<template>
  <div id="app">
    <div>
      <Navigation @left-content="leftContent" />
    </div>
    <div id="lowerContent">
      <template v-if="showLeftContent">
         //...
      </template>

      <div id="mainPane">
         //...
      </div>
    </div>
  </div>
</template>

<script>
  //...
  data() {
    return {
      showLeftContent: true
    }
  },
  methods: {
    leftContent(value) {
      this.showLeftContent = value
    }
  }
};
</script>
๐Ÿ‘คSovalina

2๐Ÿ‘

A basic approach in a parent-child component relationship is to emit events from the child and then listen and handle that event in the parent component.

However, Iโ€™m not sure that approach works when working with the router-view. This person solved it by watching the $route attribute for changes. https://forum.vuejs.org/t/emitting-events-from-vue-router/10136/6

You might also want to look into creating a simple event bus using a vue instance, or using vuex.

๐Ÿ‘คlukebearden

1๐Ÿ‘

If youโ€™d like to access the data property (or props, options etc) of the root instance, you can use this.$root.$data. (Check Vue Guide: Handling Edge)

For your codes, you can change this.$root.$data.showLeftContent to true/false in the hook=mounted of other Components, then when Vue creates instances for those components, it will show/hide the left side panel relevantly.

Below is one demo:

Vue.config.productionTip = false
Vue.component('child', {
  template: `<div :style="{'background-color':color}" style="padding: 10px">
                Reach to root: <button @click="changeRootData()">Click me!</button>
                <hr>
                <slot></slot>
             </div>`,
  props: ['color'],
  methods: {
    changeRootData() {
      this.$root.$data.testValue += ' :) '
    }
  }
})

new Vue({
  el: '#app',
  data() {
    return {
      testValue: 'Puss In Boots'
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
  <h2>{{testValue}}</h2>
  <child color="red"><child color="gray"><child color="green"></child></child></child>

</div>
๐Ÿ‘คSphinx

Leave a comment