Beautiful and compact overview page

Customized widgets are normal.

I’ve not experienced that problem. But I also haven’t messed with that sort of thing in a long time. I used to have a widget on my main Overview page showing all the information about what’s playing on one of the Google Chromecasts/Hubs. But the widget would only appear when something is actually playing. I never had an issue where I had to refresh the page to get them to show up or disappear.

If you have to refresh, and that’s the behavior in OH 5 right now, an issue should be filed as I’d consider that to be a bug.

Most of the places I use it now is in the oh-repeater cards but that is less about visibility and more just filtering out those rows that don’t need to be shown.

See Battery Level Status for how you might do that using oh-repeater, which is a “normal tool”.

The first part is just defining properties which makes the widget reusable. The “magic” is in the title and the repeater loop.

For the title I use

'=props.title + ": " + ((items[props.minLevel].displayState ===
    undefined) ? items[props.minLevel].state :
    items[props.minLevel].displayState)'

This actually could be written more concisely with additions that have been made to OH since OH 3 when I wrote it. But basicailly what it does is show the title configured in the properties and the value of the battery with the minimum charge percentage (which is calculated using a Group and the MIN aggregation function.

But you could use something like a Group with the count of open windows.

Then the oh-repeater for the batteries is

    - component: oh-repeater
      config:
        filter: Number.parseFloat(items[loop.item.name].state) <= props.max
        for: item
        fragment: true
        groupItem: =props.minLevel
        sourceType: itemsInGroup
      slots:
        default:
          - component: oh-list-item
            config:
              badge: "=(items[loop.item.name].displayState === undefined) ? loop.item.state :
                items[loop.item.name].displayState"
              badgeColor: '=(Number.parseFloat(loop.item.state) > props.green) ? "green" :
                (Number.parseFloat(loop.item.state) > props.orange) ? "orange" :
                "red"'
              icon: '=(Number.parseFloat(loop.item.state) > props.green) ? "f7:battery_100" :
                (Number.parseFloat(loop.item.state) > props.orange) ?
                "f7:battery_25" : "f7:battery_0"'
              iconColor: '=(Number.parseFloat(loop.item.state) > props.green) ? "green" :
                (Number.parseFloat(loop.item.state) > props.orange) ? "orange" :
                "red"'
              item: =loop.item.name
              title: =loop.item.label

oh-repeater loops over a number of Items and creates a separate row for each. The filter makes it so only those batteries that are below the threshold are rendered., Then the stuff under slots control how each row gets rendered. You could use something as simple as a plain old oh-label-item instead of messing with the badge and changing icon color and such. Again, there are ways to make these expressions easier to read and shorter that didn’t exist when I wrote the widget.

You might be able to use my lights widget with some modifications. I’ve not published this one to the marketplace because I have some specific customizations that won’t be generally applicable (e.g. the Christmas lights handling).

When I turn on “Tis the Season” some more lights will appear.

The code for the widget is as follows:

uid: all_lights
tags:
  - card
  - lights
props:
  parameters:
    - description: A text prop
      label: Prop 1
      name: prop1
      required: false
      type: TEXT
    - context: item
      description: An item to control
      label: Item
      name: item
      required: false
      type: TEXT
  parameterGroups: []
timestamp: Feb 11, 2021, 3:03:59 PM
component: f7-card
config:
  title: Lights
slots:
  default:
    - component: oh-list
      slots:
        default:
          - component: oh-repeater
            config:
              fragement: true
              for: item
              sourceType: itemsWithTags
              itemTags: Switch,Light
              filter: loop.item.label.includes("Christmas") == false ||
                items.TisTheSeason.state == "ON"
            slots:
              default:
                - component: oh-toggle-item
                  config:
                    icon: f7:lightbulb
                    iconColor: '=(loop.item.state == "ON") ? "yellow" : "gray"'
                    color: '=(loop.item.state == "ON") ? "yellow" : "gray"'
                    title: =loop.item.label
                    item: =loop.item.name

This oh-repeater matches all the Items tagged with the semantic tags “Switch” and “Light” and, if TisTheSeason is OFF it filters out those with “Christmas” in the label. That’s how I control which lights appear.

The list Item widgets are just simple oh-toggle-item widgets with some color changing icons. I will say that the color changing doesn’t happen without a page refresh but that’s always been the case. I can’t remember if I ever got around to filing an issue for that.

To meet your requirement, I’d change the title to use an expression to pull the number of light that are ON, probably from a Group that keeps count with an aggregation function.

What’s really cool about this widget though is if you add or remove an Item, the widget adjusts itself automatically. I never have to edit this widget, it finds all the lights based on the tags.

Shutters can be a tiny bit more complicated because their state is a number. But it would be the same approach as above only you’d test for == 0 or == 100 (depending on what number represents closed).

I would probably use an on-list-card for this and add an oh-label-item widget for each scene. I don’t know if there is a way to make this dynamic and use the oh-repreater-card unless you created Items to command the scenes instead of having the widget trigger the scene directly.