I have vue component which I use inside himself - data can have array with subelements and I use this array to render them in loop, and next level, next level etc. according to nesting level.
Now I would like to run child method from parent and then - if statements are ok, also call it to child, next level etc.
I use
<mycomponent ref="myFirstLevelRefName" (...) ></mycomponent>
and then:
this.$refs.myFirstLevelRefName
to call first-level childs. But what about about child nodes? I use them in view in that way:
<mycomponent v-for="(subElement, index) in getSubelements()" ref="???" v-bind:data="subElement" v-bind:key="index" ></mycomponent>
I tried sent this.$refs from child level to console, but it's empty.
How should I set ref name in nested elements and then call them from parent?
To access child component's data from parent with Vue. js, we can assign a ref to the child component. And then we can access the child component data as a property of the ref. to assign the markdown ref to the markdown component.
Referencing DOM Elements in Vue # Vue can store references to DOM elements in a property called $ref . The first thing we have to do, is add a ref attribute to the element we want to reference in our Javascript. The value of the ref attribute will be the name of it within the $ref property.
While it is technically possible to access $refs
of nested children...
Vue.component('mycomponent', { template: "#mycomponent", }); new Vue({ el: '#app', mounted() { console.log( 'Second level <input>\'s value:', this.$refs.myFirstLevelRefName.$refs.mySecondLevelRefName.value ) } })
<script src="https://unpkg.com/vue/dist/vue.min.js"></script> <template id="mycomponent"> <div> <input ref="mySecondLevelRefName" value="Hello"> </div> </template> <div id="app"> <mycomponent ref="myFirstLevelRefName"></mycomponent> </div>
A way of performing parent/deep child, or deep ancestor/sibling communication, for simple scenarios, is using an event hub. (For complex scenarios, see Vuex.)
You would create a global variable:
var eventHub = new Vue(); // use a Vue instance as event hub
To emit events you would use in any component:
eventHub.$emit('myevent', 'some value');
You would, then, in any other component, to listen to that event. The action of that event could be anything, including a method call (which is what you want):
eventHub.$on('myevent', (e) => { console.log('myevent received', e) // this.callSomeMethod(); });
Demo:
var eventHub = new Vue(); // use a Vue instance as event hub Vue.component('component-first', { template: "#component-1st", methods: { myMethod() { eventHub.$emit('myevent', 'some value'); } } }); Vue.component('component-second', {template: "#component-2nd"}); Vue.component('component-third', { template: "#component-3rd", created() { eventHub.$on('myevent', (e) => { this.check(); }); }, methods: { check() { console.log('check method called at 3rd level child'); } } }) new Vue({ el: '#app', data: { message: 'Hello Vue.js!' } })
<script src="https://unpkg.com/vue/dist/vue.min.js"></script> <template id="component-1st"> <div> 1st level component <button @click="myMethod">Trigger event at 1st level component that will call 3rd level child's method</button> <hr> <component-second></component-second> </div> </template> <template id="component-2nd"> <div> <component-third></component-third> </div> </template> <template id="component-3rd"> <div><h1>3rd level child</h1></div> </template> <div id="app"> <component-first></component-first> </div>
Note: If creating a dedicated instance as event hub is something complicated in your environment, you can replace eventHub
with this.$root
(inside your components) and use your own Vue instance as hub.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With