2

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?

3 Answers 3

2

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.

Sign up to request clarification or add additional context in comments.

2 Comments

This looks promising. I've only got 12 widgets built but I have 45 more to build. Looks like this could save me a lot of technical debt. I'll test tomorrow
Worked perfectly and allowed me to easily refactor about 100 extra lines of code
1

If you're happy hard-coding the numeric digits:

:widgetData="widgetData[widget1]"

and so on

Comments

1

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" />

4 Comments

It needs to be possible to display the widgets in any order. This would work if you change your data order each time.
@whla Ok, I'll push an update around that, thanks for the catch.
Yes they need to be in any order and there are multiple layouts. 1 layout might have 3 widgets, another may have 12 for example. The placement of the widget is unpredictable and based on where the user puts it. I'm pretty limited to the data - I have to have all widget props in the dashboard record. Not the way I'd like but that's the restrictions I'm dealing with. Also because it's in a grid a v-for wouldn't work without major hacking
@YestheCia all those requirements should really be in the question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.