Echart with dynamic oh-data-series

Hello Everyone,

I try to create a widget to display the realtime power consumption in my house.
The result I would like to achieve is something like that:

But what I would also like, is to dynamically construct the oh-data-series so configuration of the widget is simple.

I first give a try with oh-repeater, but hit the problems that oh-repeater don’t work with echart (Oh-repeater not working for oh-time-series in oh-chart).
The idea was to pass a group of items as a parameter, and iterate it with oh-repeater.

I also try by feeding directly JSON from an item to the oh-data-series. The idea was to construct the Json from a rule.

The following code is working well, giving the result show above.

uid: widget_1dcd9ac689
tags: []
props:
timestamp: May 8, 2024, 7:17:40 PM
component: f7-card
config:  
  title: "TestJSon"
  content: =@@'TestJSon'
slots:
  default:
    - component: oh-list
      slots:
        default:
          - component: oh-chart
            config:
              label: Power
              legend:
                top: 5%
                left: center
                show: true
            slots:
              series:
                - component: oh-data-series
                  config:
                    type: pie
                    avoidLabelOverlap: false,
                    labelLine:
                      length: 30
                    radius:
                      - 40%
                      - 60%
                    label:
                      show: true
                      formatter: "{b} {c}"
                      backgroundColor: "#F6F8FC"
                      borderColor: "#8C8D8E"
                      borderWidth: 1
                      borderRadius: 4
                      padding: 20
                    data:
                      [{'value':'20','name':'Hoven'},{'value':'30','name':'Dishwasher'},{'value':'50','name':'Light'}]                      

But if I replace the code by an item state:

uid: widget_1dcd9ac689
...
                    data:
                      =item.TestJSon.state        

I’ve got the following results:
image

It seems because oh-data-series in this case interprete the data as a string, and not as a Json.
I get the same results if I put into data the following code:

                    data:
                      "[{'value':'20','name':'Hoven'},{'value':'30','name':'Dishwasher'},{'value':'50','name':'Light'}]"                  

Does someone has any idea how to make this working ?

Thanks,
Laurent.

If it’s coming in as an item state, you need to parse that string:

data: =JSON.parse(item.TestJSon.state)

If you want to build the data dynamically and not use an item state, you can also do so. If you have a fixed number of elements then it’s trivial:

data:
  - name: 'Name 1'
    value: =items.Item1.state
  - name: 'Name 2'
    value: =items.Item2.state
...

If you have a dynamic number of elements, or want to use your group, it gets a little more difficult. You have to have the repeater outside the chart to create the array of data that you want. This means that 1) you need to then restrict the repeater’s children to only be visible during the first repeater iteration and 2) modify the repeater’s source array so that it matches the array that data expects.

- component: oh-repeater
  config:
    for: itemArray
    sourceType: itemsInGroup
    groupItem: youGroupItem
    map:  |
      loop.itemArray_source.map( x =>
        {
          name: x.label,
          value: x.stat
        }
      )
    fragment: true
  slots:
    default:
      - component: oh-chart
        config:
          visible: =loop.itemArray_idx == 0
          label: Power
          legend:
            top: 5%
            left: center
            show: true
        slots:
          series:
            - component: oh-data-series
              config:
                type: pie
                avoidLabelOverlap: false,
                labelLine:
                  length: 30
                radius:
                  - 40%
                  - 60%
                label:
                  show: true
                  formatter: "{b} {c}"
                  backgroundColor: "#F6F8FC"
                  borderColor: "#8C8D8E"
                  borderWidth: 1
                  borderRadius: 4
                  padding: 20
                data: =loop.itemArray

Hello,

Thanks a lot for your quick answer.
Solution 2 is great; I wasn’t knowing about the mapping functionality of the oh-repeater!

After some tries, i get the following result with this solution:

For some unknown reason, I wasn’t able to make the solution 1 with JSON.parse work.
When testing with this code, the chart stays empty.

uid: widget_1dcd9ac689
tags: []
props:
  parameters: []
  parameterGroups: []
timestamp: May 10, 2024, 11:00:35 AM
component: f7-card
config:
  title: TestJSon
slots:
  default:
      - component: oh-label-item
        config:
          title: =items.TestJSon.state
          item: TestJSon
      - component: oh-chart
        config:
          visible: =loop.itemArray_idx == 0
          label: Power
          legend:
            top: 5%
            left: center
            show: true
        slots:
          series:
            - component: oh-data-series
              config:
                type: pie
                avoidLabelOverlap: false,
                labelLine:
                  length: 30
                radius:
                  - 60%
                  - 80%
                label:
                  show: true
                  formatter: "{b} {c}W"
                  backgroundColor: "#F6F8FC"
                  borderColor: "#8C8D8E"
                  borderWidth: 1
                  borderRadius: 4
                  padding: 5
                data: =JSON.parse(items.TestJSon.state)

I don’t know if I miss something, or if the JSON.parse don’t work correctly in oh-chart context.

Thanks,
Laurent.

Forget about It, I finally manage to make solution 1 work as well.
I realize that my test Json in the items was not correctly formatted :frowning:

Thanks a lot for your help.

Laurent.