I want to use the same component twice from a parent component; all that was stopping me was the use of an ID for a dropdown in the subcomponents! So I currently have duplicated the subcomponent.
My parent component:
<template>
<div id="compare-page">
<div class="row">
<div class="col-md-12">
<div class="row campaign-overview">
<div class="col-md-4">
<h2>{{ campaign.name }}</h2>
<strong>Published</strong>
<strong>Starts: {{ campaign.start_date }} - Ends: {{ campaign.end_date }}</strong>
</div>
<div class="col-md-4 text-right">
<select name="daterange" id="" @change="onChangeDaterange($event)">
<option v-for="(daterange, index) in dateranges" v-bind:key="daterange.index" :value="index" :data-start="daterange.start" :data-end="daterange.end" :selected="daterange.optionSelected == 1">{{ index }}</option>
</select>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<left-device ref="leftDevice"></left-device>
</div>
<div class="col-md-6">
<right-device ref="rightDevice"></right-device>
</div>
</div>
</div>
</template>
<script>
import left from './compared_device_component_left.vue';
import right from './compared_device_component_right.vue';
export default {
components: {
'left-device': left,
'right-device': right,
},
mounted() {
this.fetchCampaignData().then(result => {
});
},
data() {
return {
campaign_id: this.$route.params.campaign_id,
campaign: [],
dateranges: [],
leftDevice: '',
rightDevice: ''
}
},
methods: {
fetchCampaignData() {
return this.$http.get('/api/portal/campaign/' + this.campaign_id + '/campaign?' + this.axiosParams)
.then(function(data){
return data.json();
}).then(function(data){
this.campaign = data.campaign;
this.dateranges = data.dateranges;
});
},
onChangeDaterange(event) {
this.$router.push('?range=' + event.target.value);
this.$refs.leftDevice.onChangeDaterange(event);
this.$refs.rightDevice.onChangeDaterange(event);
},
},
computed: {
axiosParams() {
const params = new URLSearchParams();
if(this.$route.query.range) params.append('range', this.$route.query.range);
return params;
}
},
}
</script>
<style lang="scss">
</style>
One of my subcomponents
<template>
<div>
<div class="row device-overview">
<div class="col-md-4">
<select name="devices" id="deviceLeft" @change="onChangeDevice($event)">
<option v-for="(device, index) in devices" v-bind:key="device.index" :value="index" :data-device_id="device.device_id" :data-address="device.address" :selected="device.optionSelected == 1">{{ device.device_id }} | {{ device.address }}</option>
</select>
</div>
</div>
<div class="row totals">
<div class="col-md-4 card">
<div class="card-body">
<h5 class="card-title">Total Interactions</h5>
<p class="card-text">{{ total_interactions }}</p>
</div>
</div>
<div class="col-md-4 card">
<div class="card-body">
<h5 class="card-title">Average Interactions Per Day</h5>
<p class="card-text">{{ average_daily_interactions }}</p>
</div>
</div>
<div class="col-md-4 card">
<div class="card-body">
<h5 class="card-title">Total Average Dwell Time</h5>
<p class="card-text">{{ average_dwell_time }}s</p>
</div>
</div>
</div>
<div class="row interactions">
<div class="col-md-12">
<h5>Total Interactions Per Product</h5>
<table class="table table-condensed table-hover">
<tbody>
<tr>
<td class="">Tag</td>
<td class="">Mapped Product</td>
<td class="">Lifts</td>
</tr>
<tr v-for="interaction in table_product_interactions">
<td class="">{{ interaction.tag }}</td>
<td class="">{{ interaction.mapping }}</td>
<td>{{ interaction.tag_count }}</td>
</tr>
</tbody>
</table>
</div>
<div class="col-md-12">
<h5>Total Interactions Per Day</h5>
<div class="chart" ref="chartdaily"></div>
</div>
</div>
<div class="row interactions">
<div class="col-md-8">
<h5>Total Interactions Per Hour</h5>
<div class="chart" ref="charthourly"></div>
</div>
</div>
</div>
</template>
<script>
import * as am4core from "@amcharts/amcharts4/core";
import * as am4charts from "@amcharts/amcharts4/charts";
import am4themes_animated from "@amcharts/amcharts4/themes/animated";
am4core.useTheme(am4themes_animated);
export default {
mounted() {
this.fetchData(null).then(result => {
this.chartTotalPerDay();
this.chartTotalPerHour();
});
},
data() {
return {
campaign_id: this.$route.params.campaign_id,
campaign: [],
dateranges: [],
device: [],
devices: [],
total_interactions: '',
average_daily_interactions: '',
average_dwell_time: '',
interaction_type: '',
chart_daily_interactions: [],
chart_hourly_interactions: [],
table_product_interactions: []
}
},
methods: {
fetchData(deviceID) {
// Use JS to get by ID!
var device = document.getElementById("deviceLeft");
// ... call to API
},
chartTotalPerDay() {
// ...
},
chartTotalPerHour() {
// ...
},
onChangeDaterange(event) {
// Use JS to get by ID!
var device = document.getElementById("deviceLeft");
// st cookie
document.cookie = "deviceLeft="+device.value;
this.fetchData(device.value).then(result => {
this.chartTotalPerDay();
this.chartTotalPerHour();
});
},
onChangeDevice(event) {
// st cookie
document.cookie = "deviceLeft="+event.target.value;
this.fetchData(event.target.value).then(result => {
this.chartTotalPerDay();
this.chartTotalPerHour();
});
}
},
created() {
},
computed: {
axiosParams() {
const params = new URLSearchParams();
if(this.$route.query.range) params.append('range', this.$route.query.range);
return params;
}
},
filters: {
},
directives: {
},
}
</script>
<style lang="scss">
.interactions {
h5 {
text-align: center;
}
}
.chart {
min-height: 550px;
}
</style>
I am currently using
var device = document.getElementById("deviceLeft");
...in my duplicated left/right subcomponents (this is 'left' and I also have 'right').
Should I use a 'ref' for my devices dropdown, so that each instance of the subcomponent is looking at the devices dropdown relative to that instance? Currently if I merge these into one the devices dropdown ID is the same for both instances and therefore I get incorrect ID in one of the instances!
Any helpful pointers would be much appreciated.
Thanks,
K...
question from:
https://stackoverflow.com/questions/65842646/using-same-vue-component-twice-in-same-parent-component-how-to-differentiate