A couple of simple oh-repeater examples

Tags: #<Tag:0x00007fc8f6062e50>

Edit: Corrected the way to obtain the Item’s state and misspelling of fragment.
Edit: Changed the status example to use oh-list-item instead of oh-label-item.

I’ve finished customizing the automatically generated parts of my overview page and now I’m building up the Overview page. As part of that page I’ve created a couple of custom widgets that use oh-repeater to dynamically populate a list based on tags and the states of various Items. I thought they might be useful examples so here they are.

All Lights

This is a widget that shows all my light switches in a list. The tricky part about it is it will only show the Christmas light Items if “Tis the Season” is turned on. This makes the widget smart enough to adjust during the season where I have more lights to control. :slight_smile:

NOTE: When it expands it doesn’t really work quite right with dynamic icon colors and such until a refresh.

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:
              for: item
              sourceType: itemsWithTags
              itemTags: Switch,Light
              filter: loop.item.label.includes("Christmas") == false || items.TisTheSeason.state == "ON"
              fragment: true
            slots:
              default:
                - component: oh-toggle-item
                  config:
                    icon: f7:lightbulb
                    iconColor: '=(items[loop.item.name].state == "ON") ? "yellow" : "gray"'
                    color: '=(items[loop.item.name].state == "ON") ? "yellow" : "gray"'
                    title: =loop.item.label
                    item: =loop.item.name

I don’t use the properties so probably should remove them at some point. The widget gets all the Items tagged with Switch and Light. It then filters out all those with “Christmas” in the name, unless TisTheSeason is ON. For each one of those it creates an entry in the list.

Service Status

I’ve a number of Items that monitor for the online status of devices and services that are used as part of my home automation. If any of these relevant services go offline, this widget will show that. At all other times it just has an “all online” message.

NOTE: The title of the card appears not to change until I refresh the page. :frowning:

uid: all_services
tags:
  - card
  - services
props:
  parameters: []
  parameterGroups: []
timestamp: Feb 11, 2021, 3:36:18 PM
component: f7-card
config:
  title: '="Service Status: " + (items.ServiceStatuses.state == "ON") ? "All Services Online" : "Offline"'
slots:
  default:
    - component: oh-list
      slots:
        default:
          - component: oh-repeater
            config:
              fragement: true
              for: item
              sourceType: itemsWithTags
              itemTags: Status,Power
              filter: items[loop.item.name].state != "ON" && items[loop.item.name].state != "OL"
            slots:
              default:
                - component: oh-list-item
                  config:
                    icon: f7:wifi_slash
                    iconColor: red
                    title: =loop.item.label
                    item: =loop.item.name
                    badge: OFFLINE
                    badgeColor: red

NUT’s status isn’t an ON/OFF so I had to add expressions to handle NUT’s “OL” online status in addition to Network Binding’s and MQTT LWT Channels ON/OFF.

I don’t do any dynamic changes to the list widgets themselves since the Item will only be shown when it’s offline.

Lessons Learned

Everyone should be using oh-repeater all the time! This feature is huge when it comes to quickly building widgets that include lots of similar Items. And to make it even better, the widget will dynamically adjust as you add more Items or remove Items from the model.

10 Likes

Brilliant work on the light widget. The only thing im finding is the Colour and icon colour are not updating unless you update the page. The switch moves no worries. But the colour stays grey until i refresh the page then its yellow.

Any ideas?

I see the same behavior when I flip the TisTheSeason switch which changes the number of entries in the list. But after that point it works as expected for me.

Do i see it right that you use the sematic model to select appropriate items to display?

That is for me the first approach to use the semantic model. This is maybe morr elegant than groups.

Thanks for the hint.

I would like to add the link to the documentation, I just found it yesterday while I was trying to find a sourcetype for all items of a group:

4 Likes

Thank you for sharing this: have you found out how the items are sorted when you use the repeater component? Is it always (different device, session, after oh restart etc.) the same order or is it random?

This can be explained: beware when using loop.item.state, this is part of the result of the API request the oh-repeater makes to query the items, so it will not be updated. You want to use items[loop.item.name].state instead.

Great examples! This should copied over or linked in the docs article, there’s a discussion at Component docs by AndyXMB · Pull Request #900 · openhab/openhab-webui · GitHub to discuss their structure.

PS: you have a typo in fragement => fragment.

I haven’t spent enough time with it to answer these questions. I don’t really care too much if the order is consistent. So far they have remained consistent but I don’t know what defines the order.

Good to know. I’ll correct the examples above and look at that github issue as well. I just threw these together because I wanted to see how oh-repeater works. It was easier than I thought and super powerful.

I’m happy people are finding these useful. My overall goal was to get some simple examples posted because even though the awesome examples like your keypad widget and Rainer’s weather widget are really really cool, for me at least they are beyond my understanding.

Of course, nothing wrong with posting examples on the forum. I still have a dozen of tabs open with good examples that I’d like to move to (or link from) the reference docs. Some common gotchas like “don’t use loop.item.state it’s not kept updated” should ultimately be documented there as well, so there is less of a need to search in the forum - often after trial & error - to figure these things out.

Hi Rich,
how did you managed to get rid of the item’s states in favor of the badge in your “services” example?

I’m using similar code and getting this:

Code:

       - component: oh-repeater
            config:
              for: i
              sourceType: itemsWithTags
              itemTags: =props.semTag
              fetchMetadata: semantics,widgetOrder,uiSemantics
              filter: 'vars.detailsOn ? true : loop.i.state != "OFF"'
            slots:
              default:
                - component: oh-label-item
                  config:
                    icon: =props.listIcon
                    iconColor: '=loop.i.state != "OFF" ? "red" : "green"'
                    footer: =loop.i.metadata.uiSemantics.config.preposition + loop.i.metadata.uiSemantics.config.location
                    title: =loop.i.metadata.uiSemantics.config.equipment
                    item: =loop.i.name
                    badge: '=loop.i.state != "OFF" ? "wechseln" : " ok "'
                    badgeColor: '=loop.i.state != "OFF" ? "red" : "green"'

Even if I omit the…

item: =loop.i.name

… I always get some hyphen “-” on right end of the list elements of type oh-label-item. Can’t spot any relevant difference to your widget code :frowning:

Any idea?

Go to the Item and set the State Description metadata’s Pattern field to a space. Of course that will blank it out everywhere so you’ll want to override the default stand alone widget and default cell widget too so you can see the state in the other widgets as necessary.

I had already done that so forgot to mention it above.

1 Like

Ouch. :wink:
… but clever …

Thanks for the hint!

I suppose you could always recreate the list widget using the raw f7 widgets and omit the part that displays the Item’s state after the badge.

Thanks to Philipp,
who made me aware of the UI components documention:

Can’t believe, that I haven’t noticed that before…

According to it, in contrast to the oh-label-item there is also a oh-list-item without the item state on the right already:

This eases the above task “replace state by badge” even more:

       - component: oh-repeater
            config:
              for: i
              sourceType: itemsWithTags
              itemTags: =props.semTag
              fetchMetadata: semantics,widgetOrder,uiSemantics
              filter: 'vars.detailsOn ? true : loop.i.state != "OFF"'
            slots:
              default:
                - component: oh-list-item
                  config:
                    icon: =props.listIcon
                    iconColor: '=loop.i.state != "OFF" ? "red" : "green"'
                    footer: =loop.i.metadata.uiSemantics.config.preposition + loop.i.metadata.uiSemantics.config.location
                    title: =loop.i.metadata.uiSemantics.config.equipment
                    item: =loop.i.name
                    badge: '=loop.i.state != "OFF" ? "wechseln" : " ok "'
                    badgeColor: '=loop.i.state != "OFF" ? "red" : "green"'

This gives:

Quite happy with that :wink:

2 Likes

I’ll change the OP above to use oh-list. I should have been using it from the start but because I already went through changing all the state descriptions on my items it didn’t occur to me. Good find!

Not realy related to the widget, but how do you monitor this? With the network binding? Do you have a small example?

It depends on the device. If it’s reporting stuff as MQTT I watch the LWT topic and set a Switch Item to OFF when the LWT message is received. For services or machines I use the Network Binding. For devices that might fail silently that can’t be pinged (e.g. battery powered Zwave devices) I use Design Patterns: Generic Is Alive. It’s all really straight forward really. When the device or service is offline, the Switch Item is OFF. When it’s online the Switch Item is ON.

Thanks for your examples, I’m using your “All lights” Widget to show all lights which are “ON”. But the list is long in the evening … so I just thought if it’s possible to limit the repeater that he only shows the last 6 lights which switch to on? Any idea if that is possible? :slight_smile:

Thank you for this example. This widget populates with my tagged items just fine. I can move the toggle to “on” and turn on a light. However, the widget does not indicate the on status with the icon color change. Also, I cannot turn the light off once it is turned on. If I add a widget from the semantic model to toggle on/off a light, that works just fine.

There must be something missing in my config somewhere. Any ideas would be very much appreciated.

All I know is the code I posted works for me. Since I have no view into the code you have. :man_shrugging: