Reputation: 538
I am making a dashboard app where someone can add any widget in any order to their dashboard. It's all working but Im trying to kill some technical debt and clean up.
For simplicity, lets say a dashboard can have 2 widgets (Clock and Weather). These widgets need some data from the dashboard record. The widgets can be in any order on the page.
Im including them like so.
data () {
return {
widget1: 'Clock',
widget2: 'Weather',
widgetData: {
weather: {
long: '12.23.34',
lat: '23.34.45'
},
Clock: {
timeFormat: '24Hour',
dateFormat: 'US'
}
}
}
}
Then in the HTML
<component v-bind:is="this.widget1" :widgetData="widgetData"></component>
<component v-bind:is="this.widget2" :widgetData="widgetData"></component>
Now what I want to do is
<!-- if this.widget1 is Clock then :widgetData should equals widgetData.Clock -->
<component v-bind:is="this.widget1" :widgetData="widgetData.this.widget1"></component>
<!-- if this.widget2 is Weather then :widgetData should equals widgetData.Weather -->
<component v-bind:is="this.widget2" :widgetData="widgetData.this.widget2"></component>
so that the this.widget1 will populate both the :is and drill down into the :widgetData object so Im not passing the whole object to each component
My example take into consideration only 2 widgets but in reality a simple dashboard can have up to 9.
I've tried pretty much every thing such as
:widgetData="widgetData.{{this.widget1}}"
:widgetData="widgetData.${this.widget1}"
etc.
Any ideas?
Upvotes: 2
Views: 1028
Reputation: 36349
So, if it were me, I'd reframe things just a bit. Rather than just calling the widget component explicitly for each, I'd actually use the object you created. Given:
data () {
return {
widgetData: {
Weather: {
long: '12.23.34',
lat: '23.34.45'
},
Clock: {
timeFormat: '24Hour',
dateFormat: 'US'
}
}
}
}
Given that, your keys are the same as your widget type and the data is the value. So you can do this:
<div v-for="(value, key) in widgetData">
<component :is="key" :widgetData="value" />
</div>
Or if you don't want the wrapper div you should also be able to just use the component:
<component v-for="(value, key) in widgetData" :is="key" :widgetData="value" />
-- If, as the comments suggest, the order is something that can be set, then I'd actually change your data model slightly to accomplish the same thing. In this case, the index of the widget in the array would be the order the widgets go in:
data () {
return {
widgetData: [
{ type: "Weather",
data: {
long: '12.23.34',
lat: '23.34.45'
},
{ type: "Clock",
data: {
timeFormat: '24Hour',
dateFormat: 'US'
}
}
]
}
In that case the component binding would be like so:
<component v-for="widget in widgetData" :is="widget.type" :widgetData="widget.data" />
Upvotes: 1
Reputation: 811
You could try using a function that you would take widget type and return desired data.
:widgetData="getWidgetData(this.widget1)"
...
method: {
getWidgetData(widgetType) {
if (widgetType == "Clock") {
return clockData;
}
if (widgetType == "Weather") {
return weatherData;
}
}
}
This will especially prove useful if your store becomes more complex than an array.
Upvotes: 2
Reputation: 14053
If you're happy hard-coding the numeric digits:
:widgetData="widgetData[widget1]"
and so on
Upvotes: 1