6

I am struggling for this to work. I need to access the selected value in the ChooseLangComponent from the FormComponent. Is there any direct way to do this or we have to pass it from the parent component (act like middle man)? I already tried with $emit on ChooseLangComponent and v-on:.. on FormComponent but didn't work.

ChooseLangComponent:

<template lang="html">
    <div class="choose-lang">
        <select v-model="selected">
            <option v-for="lang in langs" v-bind:value="lang.value">{{lang.text}}</option>
        </select>
    </div>
</template>

<script>
    export default {
        data() {
            return {
                selected: 'en',
                langs: [
                    { text: 'English', value: 'en' },
                    { text: 'German', value: 'ge' },
                ]
            }
        }
    }
</script>

FormComponent:

<template lang="html">
    <div class="form-name">
        <div class="inputs">
            <input type="text" v-model="nameText" v-on:keyup.enter="send_name">
        </div>
    </div>
</template>

export default {
    data() {
        return {
            nameText: '',
        }
    },
    methods: {
        send_name() {
              // I need the selected language here
        }
    }
}

The parent component:

<div id="app">
    <choose-lang></choose-lang>
    ...
    <form-comp></form-comp>
</div>

...
Vue.component('choose-lang', require('./components/ChooseLangComponent.vue'));
Vue.component('form-comp', require('./components/FormComponent.vue'));

const app = new Vue({
el: '#app',
data: {
    ...
});
Hula Hula
  • 553
  • 8
  • 20

1 Answers1

11

Okay there are 2 easy ways and one more which involves the Vuex, if your app is large scale.

First way is creating the Event Bus - idea is emitting Events in one hub and then catching them where It's needed.

const Bus = new Vue({})

Vue.component('lang', {
       template: '#lang-tmp', 
       data() {
            return {
                selected: 'en',
                langs: [
                    { text: 'English', value: 'en' },
                    { text: 'German', value: 'ge' },
                ]
            }
        },
        created() {
          this.changeLang()
        },
        methods: {
          changeLang() {
            Bus.$emit('langChanged', this.selected)
          }
        }
})

Vue.component('frm', {
  template: '#frm-tmp',
  data() {
    return {
      selectedItem: 'en'
    }
  },
  created() {
    Bus.$on('langChanged', (selected) => {
      this.selectedItem = selected
    })
  }
})

const app = new Vue({

  el: '#app'

})

http://jsbin.com/siyipuboki/edit?html,js,output

Second way is creating sort of store - plain object that would hold the state of selected item

const store = {
  data: {
    selected: null
  }
}

Vue.component('lang', {
       template: '#lang-tmp', 
       data() {
            return {
                selected: 'en',
                langs: [
                    { text: 'English', value: 'en' },
                    { text: 'German', value: 'ge' },
                ]
            }
        },
        created() {
          this.changeLang()
        },
        methods: {
          changeLang() {
            store.data.selected = this.selected
          }
        }
})

Vue.component('frm', {
  template: '#frm-tmp',
  data() {
    return {
      storeSelected: store.data
    }
  }
})

const app = new Vue({

  el: '#app'

})

http://jsbin.com/qagahabile/edit?html,js,output

Also please check this VueJS access child component's data from parent

Community
  • 1
  • 1
Belmin Bedak
  • 9,011
  • 2
  • 40
  • 44
  • Thank you, I will accept it as soon as I test it on my project. I would like to give you +1, but can't because of repu... – Hula Hula Apr 01 '17 at 10:16
  • There's is problem with the first method. `Bus is not defined`, refering to the Bus within the langComponent. I'm declaring `const Bus = ...` on app.js, and the components are on seperate file (don't know if that's the problem though) – Hula Hula Apr 01 '17 at 14:31
  • Sorry I don't understand, jsbin works properly without any errors. – Belmin Bedak Apr 01 '17 at 14:32
  • Could you show how you tried to implement this bus solution in your app ? – Belmin Bedak Apr 01 '17 at 14:53
  • Still, when click the button `Bus is not defined`. DO you think this error is due the the components being on diferent files? And the `const Bus = ...` on `app.ps` (question's parent component, another file) – Hula Hula Apr 01 '17 at 14:58
  • Expose bus on the window if building in webpack. – Bert Apr 01 '17 at 15:01
  • I think the solution 2 would better fit in your case - you can just create new file, export object, fill it with properties you need and import where it's needed (Check link at the end of answer) – Belmin Bedak Apr 01 '17 at 15:03
  • @BertEvans "Expose bus on the window if building in webpack" . Well done (don't know if it's good practice but it worked), just changed `window.Bus = new Vue({})` in the Belmin anwser. Thank you both – Hula Hula Apr 01 '17 at 15:32