Reputation: 629
I'm writing a "tabs" component.
I am trying to send data using the sendTabsData()
method in my code, and for some reason it's not working using $emit
.
This is my tab component code:
<template>
<div id="tabs">
<div id="tabs-cont">
<div class="tabbable-panel">
<div class="tabbable-line">
<ul class="nav nav-tabs" role="tablist">
</ul>
<div class="tab-content">
<slot></slot>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'DashboardTabs',
props: {
tabs: {
type: Object,
required: true,
default: {}
}
},
data() {
return {
displayed: '',
tabName: '',
$tabsContainer: null,
navTabs: null,
tabContent: null
}
},
created() {
},
mounted() {
this.init();
},
watch: {
},
methods: {
init: function() {
// Fetch UI elements
this.$tabsContainer = $('#tabs');
this.navTabs = this.$tabsContainer.find('.nav-tabs');
this.tabContent = this.$tabsContainer.find('.tab-content');
this.createTabs(this.tabs);
},
// Create tabs by result
createTabs: function(tabs) {
if ( this.tabs !== undefined || this.tabs.length > 0 ) {
this.setTabsBtns(tabs);
}
},
//
tabClick: function(e) {
this.changeDisplayNames(e);
this.sendTabsData();
},
// Change display names
changeDisplayNames: function(e) {
let liItem = e['target']['dataset']['displaytable'];
if (liItem) {
// Update variable table name
this.displayed = liItem;
// Remove the '$' and 'Table' text
let tableCategory = this.displayed.replace('Table', '');
tableCategory = tableCategory.replace('$', '');
// Update "global" variable of the current table
this.tabName = tableCategory.charAt(0).toUpperCase() + tableCategory.slice(1);
}
},
// Set tabs li btns
setTabsBtns: function(tabs) {
for (let key in tabs) {
this.navTabs.append(`<li class="nav-item" @click="this.tabClick"> <a href="#tab_default_${key}" class="nav-link" data-toggle="tab" data-displayTable="${tabs[key]}"> ${tabs[key]} </a> </li>`);
}
this.navTabs.find('li:first a').addClass('active');
this.displayed = this.tabs[0];
this.tabName = this.tabs[0];
},
// Set tabs content divs - not relevant if you don't want to load extra data to the DOM
setTabsContent: function(tabs) {
for (let key in tabs) {
this.tabContent.append(`<div class="tab-pane" id="tab_default_${key}"> <table class="aTable hover display" id="${tabs[key]}"> </table> </div>`);
}
this.tabContent.find('.tab-pane').first().addClass('active');
},
hideTabs: function() {
this.$tabsContainer.slideUp('slow');
},
showTabs: function() {
this.$tabsContainer.slideDown('slow');
},
// Send tab data to parent
sendTabsData: function(){
let data = {
'tabDisplayed': this.displayed,
'tabName': this.tabName
};
this.$emit('tabsData', data);
}
}
};
</script>
and this is the parent component:
<script>
// import ProgressBar from "../components/ProgressBar.vue";
// import _ from 'lodash';
import DashboardForm from "../components/DashboardForm.vue";
import DashboardTabs from "../components/DashboardTabs.vue";
export default {
name: 'testcomponent',
components: {
// ProgressBar,
DashboardForm,
DashboardTabs
},
// mixins: [GF],
data() {
return {
};
},
created() {
},
mounted() {
},
destroyed() {
},
watch: {
},
methods: {
// Submit form
formSubmit: function(data) {
console.log('Submit form here');
console.log(data);
},
// Tabs data
fetchTabsData: function(data) {
console.log('tab was clicked');
console.log(data);
}
}
}
</script>
<!-- Template -->
<template>
<div id="testcomponent">
<!-- DashboardForm -->
<DashboardForm
:useGroupFilter="true"
:useDateRange="true"
@submit="formSubmit"
/>
<!-- Main Data Container -->
<div id="data-container">
<div id="chart-container"></div>
<!-- Dashboard Tabs and Tab Container -->
<DashboardTabs
:tabs="{ 0: 'potato', 1: 'banana' }"
@tabsData="fetchTabsData"
>
<!-- Datatable -->
<!-- <DashboardDatatable/> -->
</DashboardTabs>
</div>
<!-- END data-container -->
</div>
</template>
as you can see, in my parent component, i have a submit emit that fetches data (and works fine).
The only difference between the tabs component and the form component is that the tab component generates the <li>
s that have the click event bined to.
So just to be clear with my question:
How do I send data from a child component to a parent component using $emit when in this case - the element that has the click event bind to it (onClick ==> send/listen the data to the parent component) is dynamically self-generated and not "static".
EDIT: using v-for doesn't seem to get the requested result:
<li class="nav-item" @click="this.tabClick" v-for="(tab,index) in tabs">
<a :href="`#tab_default_${index}`" class="nav-link" data-toggle="tab" :data-displayTable="`${tab}`"> ${tab} </a>
</li>
I get the error:
Error in render: "TypeError: Cannot read property 'tabClick' of undefined"
Seems like it's not letting me to add a @click
Edit2:
tryed using @click.native="this.tabClick"
in v-for - doesn't result any errors but my dummy console.logs do not appear. click event doesn't run prroperly.
Upvotes: 3
Views: 1351
Reputation: 621
Your component emit a tabs
event (this.$emit('tabs', data)
), so, your parent should listen to the tabs
event : @tabs="tabsData"
instead of submit
Upvotes: 3