Example Custom List Widgets

Tags: #<Tag:0x00007f175125d950> #<Tag:0x00007f175125d7c0>

I’ve been creating a bunch of custom list widgets to use as default list widgets on my similar Items. This lets me define the widget only once and keep a consistent look and feel over how the Items are depected and work across the automatically generated cards. I figured I’d share some here as they might be useful.

Once you’ve imported them as a custom widget under Developer Tools, you can select them from the list of widget types in the “default list widget” metadata.

Because I kind of like a consistent look and feel and I like the ability to control the icons and color of the icons based on the state of Items (not necessarily the Item being displayed) I’m using all f7 icons. I kind of wish they had more IoT type icons available.

Battery Status

The action will open up a chart. It uses red and battery_0 when the level is < 25, battery_25 and yellow when between 25 and 75 (as shown) and green and battery_100 when > 75.

uid: battery_list
tags:
  - list
  - battery
props:
  parameters:
    - description: Battery name
      label: Name
      name: title
      required: false
      type: TEXT
    - context: item
      description: Battery Item to display
      label: Item
      name: item
      required: false
      type: TEXT
  parameterGroups: []
timestamp: Feb 3, 2021, 1:37:09 PM
component: oh-label-item
config:
  icon: '=(Number.parseInt(items[props.item].state) > 75) ? "f7:battery_100" : (Number.parseInt(items[props.item].state) > 25) ? "f7:battery_25" : "f7:battery_0"'
  iconColor: '=(Number.parseInt(items[props.item].state) > 75) ? "green" : (Number.parseInt(items[props.item].state) > 25) ? "yellow" : "red"'
  title: =props.title
  item: =props.item
  action: analyzer
  actionAnalyzerCoordSystem: time
  actionAnalyzerItems: =[props.item]

Electric

This is a very simple widget that just sets an orange bolt icon and will open a chart for the Item as the action. I use it for the sensor readings of my whole house energy meter.

uid: electric
tags:
  - list
  - electric
props:
  parameters:
    - description: Widget title
      label: Title
      name: title
      required: false
      type: TEXT
    - context: item
      description: Item to display
      label: Item
      name: item
      required: false
      type: TEXT
  parameterGroups: []
timestamp: Feb 2, 2021, 3:42:47 PM
component: oh-label-item
config:
  icon: f7:bolt
  iconColor: '"yellow"'
  title: =props.title
  item: =props.item
  action: analyzer
  actionAnalyzerCoordSystem: time
  actionAnalyzerItems: =[props.item]

Garage door

I have two garage door openers, each with a single sensor Item and a controller Item. I’ve assigned this widget to the sensor Item and excluded the control Item from the model since this widget handles both status and triggering the Item. But by using the sensor Item I can keep the badge on the card when a door is opened.

uid: garagedoor_list
tags:
  - list
  - garagedoor
props:
  parameters:
    - description: Door name
      label: Name
      name: name
      required: false
      type: TEXT
    - context: item
      description: Control Item
      label: Control Item
      name: control_item
      required: false
      type: TEXT
    - context: item
      description: Sensor Item
      label: Sensor Item
      name: sensor_item
      required: false
      type: TEXT
  parameterGroups: []
timestamp: Feb 3, 2021, 1:12:37 PM
component: oh-list-item
config:
  icon: '=(items[props.sensor_item].state == "CLOSED") ? "f7:house" : "f7:house_fill"'
  iconColor: '=(items[props.sensor_item].state == "CLOSED") ? "green" : "red"'
  title: =props.name
  action: command
  actionItem: =props.control_item
  actionCommand: ON
  badgeColor: '=(items[props.sensor_item].state == "CLOSED") ? "green" : "red"'
  badge: '=(items[props.sensor_item].state == "CLOSED") ? "closed" : "open"'

Humidity

A simple widget that uses the F7 drop icon. The icon will be purple when humidity is > 45, blue when between 30 and 45, and orange when under 30. I mostly use these for indoor sensors so the color coding is based on comfort level.

uid: humidity_list
tags:
  - list
  - humidity
props:
  parameters:
    - description: Widget title
      label: Title
      name: title
      required: false
      type: TEXT
    - context: item
      description: Item to display
      label: Item
      name: item
      required: false
      type: TEXT
  parameterGroups: []
timestamp: Feb 3, 2021, 11:51:38 AM
component: oh-label-item
config:
  icon: f7:drop
  iconColor: '=(Number.parseInt(items[props.item].state) > 45) ? "purple" : (Number.parseInt(items[props.item].state) > 30) ? "blue" : "orange"'
  title: =props.title
  item: =props.item
  action: analyzer
  actionAnalyzerCoordSystem: time
  actionAnalyzerItems: =[props.item]

Light Switches


A simple toggle widget using the lightbulb icon. Color is grey when it’s off and yellow when it’s on.

uid: light_list_widget
tags:
  - list
  - light
props:
  parameters:
    - description: The label for the widget
      label: Title
      name: title
      required: false
      type: TEXT
    - context: item
      description: The light switch Item
      label: Item
      name: item
      required: false
      type: TEXT
  parameterGroups: []
timestamp: Jan 28, 2021, 4:45:06 PM
component: oh-toggle-item
config:
  icon: f7:lightbulb
  iconColor: '=(items[props.item].state == "ON") ? "yellow" : "gray"'
  color: '=(items[props.item].state == "ON") ? "yellow" : "gray"'
  title: =props.title
  item: =props.item

Money

Based on the whole house energy meter I estimate my monthly electrical bill. These widgets show that estimate.

It will change color, green when it’s under 50, orange when between 50 and 200, and red when greater than 200.

uid: money_list
tags:
  - list
  - money
props:
  parameters:
    - description: Widget title
      label: Title
      name: title
      required: false
      type: TEXT
    - context: item
      description: Item to display
      label: Item
      name: item
      required: false
      type: TEXT
  parameterGroups: []
timestamp: Feb 2, 2021, 3:43:47 PM
component: oh-label-item
config:
  item: =props.item
  title: =props.title
  iconColor: '=(items[props.item].state < 50) ? "green" : (items.[props.item].state < 200) ? "orange" : "red"'
  icon: f7:money_dollar_circle
  actionAnalyzerItems: =[props.item]
  action: analyzer

Presence

Will turn red and the badge changes to “away” when not present.

uid: presence_list
tags:
  - list
  - presence
props:
  parameters:
    - description: The label for the widget
      label: Person
      name: title
      required: false
      type: TEXT
    - context: item
      description: The presence switch Item
      label: Item
      name: item
      required: false
      type: TEXT
  parameterGroups: []
timestamp: Feb 2, 2021, 4:00:22 PM
component: oh-label-item
config:
  icon: f7:person_circle
  iconColor: '=(items[props.item].state == "ON") ? "green" : "red"'
  color: '=(items[props.item].state == "ON") ? "yellow" : "gray"'
  title: =props.title
  item: =props.item
  badgeColor: '=(items[props.item].state === "ON") ? "green" : "red"'
  badge: '=(items[props.item].state === "ON") ? "PRESENT" : "AWAY"'

Temperature

Changes the color of the icon based on the current temp. > 75 is red, between 75 and 50 is orange, between 50 and 32 is blue, and anything under 32 is purple. You can see it’s a pretty nice day here today.

uid: temperature_list
tags:
  - list
  - temperature
props:
  parameters:
    - description: Widget title
      label: Title
      name: title
      required: false
      type: TEXT
    - context: item
      description: Item to display
      label: Item
      name: item
      required: false
      type: TEXT
  parameterGroups: []
timestamp: Feb 3, 2021, 11:51:12 AM
component: oh-label-item
config:
  icon: f7:thermometer
  iconColor: '=(Number.parseFloat(items[props.item].state) > 75) ? "red" : (Number.parseFloat(items[props.item].state) > 55) ? "orange" : (Number.parsFloat(items[props.item.state]) > 32) ? "blue" : "purple"'
  title: =props.title
  item: =props.item
  action: analyzer
  actionAnalyzerCoordSystem: time
  actionAnalyzerItems: =[props.item]

Door with Lock




This is another dual Item widget similar to the garage door openers. However, unlike the garage door, the lock and the door are independent from each other. The badge at the right indicates the door’s open status and the icon on the left indicates the door’s deadbolt status. Clicking on the widget causes the lock to toggle.

Now that I look at it I should use orange for open and green for closed in the badge and I can put some more text information in the subtitle. I’ll leave those as an exercise for the student. I don’t want to have to recreate the screen grabs.

uid: lock_list
tags:
  - list
  - lock
props:
  parameters:
    - description: Door name
      label: Name
      name: name
      required: false
      type: TEXT
    - context: item
      description: Control Item
      label: Control Item
      name: control_item
      required: false
      type: TEXT
    - context: item
      description: Sensor Item
      label: Sensor Item
      name: sensor_item
      required: false
      type: TEXT
  parameterGroups: []
timestamp: Feb 3, 2021, 2:35:39 PM
component: oh-list-item
config:
  icon: '=(items[props.control_item].state == "ON") ? "f7:lock" : "f7:lock_open"'
  iconColor: '=(items[props.control_item].state == "ON") ? "green" : "orange"'
  title: =props.name
  action: toggle
  actionCommand: ON
  actionCommandAlt: OFF
  actionItem: =props.control_item
  badgeColor: '=(items[props.sensor_item].state == "OPEN") ? "green" : "orange"'
  badge: '=(items[props.sensor_item].state == "OPEN") ? "open" : "closed"'

Ok ok, here’s the updated version.


uid: lock_list
tags:
  - list
  - lock
props:
  parameters:
    - description: Door name
      label: Name
      name: name
      required: false
      type: TEXT
    - context: item
      description: Control Item
      label: Control Item
      name: control_item
      required: false
      type: TEXT
    - context: item
      description: Sensor Item
      label: Sensor Item
      name: sensor_item
      required: false
      type: TEXT
  parameterGroups: []
timestamp: Feb 3, 2021, 2:35:39 PM
component: oh-list-item
config:
  icon: '=(items[props.control_item].state == "ON") ? "f7:lock" : "f7:lock_open"'
  iconColor: '=(items[props.control_item].state == "ON") ? "green" : "orange"'
  title: =props.name
  subtitle: '=(items[props.sensor_item].state == "OPEN") ? "open" : (items[props.control_item].state == "ON") ? "closed and locked" : "closed and unlocked"'
  action: toggle
  actionCommand: ON
  actionCommandAlt: OFF
  actionItem: =props.control_item
  badgeColor: '=(items[props.sensor_item].state == "OPEN") ? "orange" : "green"'
  badge: '=(items[props.sensor_item].state == "OPEN") ? "open" : "closed"'

Humidifier Switch


uid: humidifier_switch_list
tags:
  - list
  - humidifier
props:
  parameters:
    - description: Name of the humidifier
      label: Name
      name: title
      required: false
      type: TEXT
    - context: item
      description: The humidifier switch Item
      label: Item
      name: item
      required: false
      type: TEXT
  parameterGroups: []
timestamp: Feb 3, 2021, 4:21:38 PM
component: oh-toggle-item
config:
  icon: f7:drop
  iconColor: '=(items[props.item].state == "ON") ? "blue" : "gray"'
  color: '=(items[props.item].state == "ON") ? "blue" : "gray"'
  title: =props.title
  item: =props.item

Humidifier Setpoint

uid: humidifier_setpoint_list
tags:
  - list
  - humidifier
props:
  parameters:
    - description: Humidifier name
      label: Name
      name: name
      required: false
      type: TEXT
    - context: item
      description: Control Item
      label: Control Item
      name: control_item
      required: false
      type: TEXT
    - context: item
      description: Sensor Item
      label: Sensor Item
      name: sensor_item
      required: false
      type: TEXT
  parameterGroups: []
timestamp: Feb 3, 2021, 4:42:49 PM
component: oh-slider-item
config:
  icon: f7:drop
  iconColor: '=(Number.parseInt(items[props.sendor_item].state) > 45) ? "purple" : (Number.parseInt(items[props.sensor_item].state) > 30) ? "blue" : "orange"'
  title: '=props.name + ": " + items[props.control_item].state + "%"'
  unit: "%"
  min: 0
  max: 100
  step: 1
  item: =props.control_item
  scaleSteps: 10
  scaleSubSteps: 5
  color: blue
  label: true

The above probably isn’t the best example. I should use the State Description metadata to add the “%” in the title.

scaleSteps and scaleSubSteps are not really being used.

What I couldn’t capture easily was that when you drag the slider it shows the current value in a little popup above the handle.

Light Level

Note, I’m just using light sensitive resistors so the actual number reported isn’t really all that meaningful beyond small number == dark and large number == light.

uid: light_level_list
tags:
  - list
  - light
props:
  parameters:
    - description: Sensor name
      label: Name
      name: title
      required: false
      type: TEXT
    - context: item
      description: Item to display
      label: Item
      name: item
      required: false
      type: TEXT
  parameterGroups: []
timestamp: Feb 5, 2021, 3:59:02 PM
component: oh-label-item
config:
  icon: '=(Number.parseFloat(items[props.item].state) < 250) ? "f7:light_min" : "f7:light_max"'
  iconColor: '=(Number.parseFloat(items[props.item].state) < 50) ? "black" : (Number.parseFloat(items[props.item].state) < 150) ? "gray" : (Number.parsFloat(items[props.item.state]) < 350) ? "orange" : "yellow"'
  title: =props.title
  item: =props.item
  action: analyzer
  actionAnalyzerCoordSystem: time
  actionAnalyzerItems: =[props.item]

Chromecast

Ideally I’d like to convert this one into a single widget or perhaps two widgets but my experiments so far to put a button side by side to a player control or slider have been unsuccessful. So I’ve created four widgets, all of which will only be shown if the Idling Item is OFF.

uid: media_control_list
tags:
  - list
  - media
props:
  parameters:
    - description: Player name
      label: Name
      name: name
      required: false
      type: TEXT
    - description: Item prefix
      label: Prefix
      name: prefix
      required: true
      type: TEXT
  parameterGroups: []
timestamp: Feb 4, 2021, 2:14:55 PM
component: oh-player-item
config:
  icon: f7:hifispeaker
  iconColor: black
  title: =props.name
  subtitle: =items[props.prefix + "_MediaTitle"].state + " by " + items[props.prefix + "_MediaArtist"].state
  visible: =(items[props.prefix + "_Idling"].state == "OFF")
  trackItem: =props.prefix + "_MediaTitle"
  after: =items[props.prefix + "_App"].state
  artistItem: =props.prefix + "_MediaArtist"
  showRewindFFward: false
  item: =props.prefix + "_MediaControl"
uid: media_toggle_list_button
tags:
  - list
  - media
props:
  parameters:
    - description: Text to display when Item is ON
      label: On text
      name: on_label
      required: false
      type: TEXT
    - description: Text to display when Item is OFF
      label: Off text
      name: off_label
      required: true
      type: TEXT
    - context: item
      description: An item to control
      label: Item
      name: item
      required: true
      type: TEXT
    - context: item
      description: When ON the button will not be shown
      label: Idle Item
      name: idle_item
      required: true
      type: TEXT
  parameterGroups: []
timestamp: Feb 5, 2021, 3:46:21 PM
component: oh-list-item
config:
  title: '=(items[props.item].state == "ON") ? props.on_label : props.off_label'
  actionCommand: ON
  actionCommandAlt: OFF
  listButtonColor: black
  actionItem: =props.item
  action: toggle
  listButton: true
  visible: =items[props.idle_item].state != "ON"
uid: media_stop_list_button
tags:
  - list
  - media
props:
  parameters:
    - description: Text to display
      label: Label
      name: label
      required: false
      type: TEXT
    - context: item
      description: An item to control
      label: Item
      name: item
      required: true
      type: TEXT
    - context: item
      description: When ON the button will not be shown
      label: Idle Item
      name: idle_item
      required: true
      type: TEXT
  parameterGroups: []
timestamp: Feb 5, 2021, 3:46:41 PM
component: oh-list-item
config:
  title: =props.label
  actionCommand: ON
  listButtonColor: black
  actionItem: =props.item
  action: command
  listButton: true
  visible: =items[props.idle_item].state != "ON"
uid: volume_setpoint_list
tags:
  - list
  - media
props:
  parameters:
    - description: Player name
      label: Name
      name: name
      required: false
      type: TEXT
    - context: item
      description: Item
      label: Volume Item
      name: item
      required: true
      type: TEXT
  parameterGroups: []
timestamp: Feb 4, 2021, 4:16:07 PM
component: oh-slider-item
config:
  icon: '=(Number.parseInt(items[props.item].state) == 0) ? "f7:speaker_slash" : (Number.parseInt(items[props.item].state) < 25) ? "f7:speaker" : (Number.parseInt(items[props.item].state) < 50) ? "f7:speaker_1" : (Number.parseInt(items[props.item].state) < 75) ? "f7:speaker_2" : "f7:speaker_3"'
  iconColor: black
  title: =props.name
  min: 0
  max: 100
  step: 10
  item: =props.item
  scaleSteps: 10
  scaleSubSteps: 5
  color: black
  label: true
  visible: =(items[props.item.replace("Volume", "Idling")].state == "OFF")

Service Status


I’ve configured it to show ONLINE but I’ve also configured it to be invisible when the service is online.

uid: service_status_list
tags:
  - list
  - status
props:
  parameters:
    - description: Human friendly service name
      label: Service Name
      name: service
      required: false
      type: TEXT
    - context: item
      description: An item to control
      label: Item
      name: item
      required: false
      type: TEXT
  parameterGroups: []
timestamp: Feb 5, 2021, 2:20:29 PM
component: oh-label-item
config:
  title: =props.service
  icon: '=(items[props.item].state == "ON") ? "f7:wifi" : "f7:wifi_slash"'
  badgeColor: '=(items[props.item].state === "ON") ? "green" : "red"'
  badge: '=(items[props.item].state === "ON") ? "ONLINE" : "OFFLINE"'
  iconColor: '=(items[props.item].state == "ON") ? "green" : "red"'
  visible: =items[props.item].state != "ON"

I’ve also a few list widgets defined that are not created as custom widgets that I’ll paste here in case they are useful.

Cloudiness



value: " "
config:
  icon: '=(Number.parseInt(items.vCloudiness.state) > 75) ? "f7:cloud_fill" :
    (Number.parseInt(items.vCloudiness.state) > 25) ? "f7:cloud_sun" :
    "f7:sun_min"'
  iconColor: '=(Number.parseInt(items.vCloudiness.state) > 75) ? "gray" :
    (Number.parseInt(items.vCloudiness.state) > 25) ? "blue" : "yellow"'
  actionAnalyzerCoordSystem: time

Door

A simple door without anything fancy.

value: oh-list-item
config:
  badgeColor: '=(items.Garagedoor_Sensor.state == "OPEN") ? "orange" : "green"'
  badge: '=(items.Garagedoor_Sensor.state == "OPEN") ? "OPEN" : "CLOSED"'
  icon: '=(items.Garagedoor_Sensor.state == "OPEN") ? "f7:house_alt_fill" :
    "f7:house_alt"'
  iconColor: '=(items.Garagedoor_Sensor.state == "OPEN") ? "orange" : "green"'
  iconUseState: ""
  title: Garage Door

I’ll add more as I create more.

25 Likes

Reserved in case I run out of room above.

1 Like

Very nice and clean! :ok_hand:

great examples indeed! Very useful. Thanks Rich.

Hi @rlkoshak can you share the complete widget(s) for your garage door example above - how did you do the header image with text and looks like glimpse badges??

It looks very much like a home made location card!

I think you will find that is the location card. The widget is the list item only.

Ah OK I wasnt even aware that you can add your own widgets TO the location cards - so much to learn!

You can set widgets to be used as a default list item. All items in location cards are list items.
All items in cells, that you manually place on pages, are cell items.

It’s the standard Location card. All I did was configure a background image which you can do by editing the settings. See [Wiki] Building Pages in the OH 3 UI - Automatically Generated Overview Tabs for details.

1 Like

thanks Richard these are very useful I have the same garage setup. Do you have a widget with two buttons. I can’t see how to do it without getting into a mess with f7-cols and formatting. I’ve posted my feeble effort here

Is it possible to bulk add custom list widget to 50 lights.
I now have all my items in files when working and changing the model.

I have only messed with the standard oh list widgets thus far. Anything beyond that is beyond me. But I would expect that you would need to indeed use f7-cols to define the columns first.

The same way you would change anything in .items files. You’ll have to edit each one with the needed metadata to set the widget and properties.

In the .items file the Light widget would look something like:

listWidget="widget:light_list_widget"[title="Front Room Lamp"]
1 Like

Just worked out you can use the component slots to add any components not supported by the standard properties. Most of the alignment / justification challenges are solved using this. See OH flex alignment - #7 by AndyMB

That example is functionally not complete (the question was about control alignment/formatting), but I’m just about to code a ‘radio button’ based example for my own use. I’ll post the code when complete. Andy

1 Like

Tis works like a charm. Would it be possible to get rid of [title=“Front Room Lamp”] and have it use the item name instead.

You’d have to modify the widget code to use props.item instead of props.title. Though you probably really want the Item’s label, not it’s name. I don’t know for sure but you could try =items[props.item].label.

If you remove the title property from the widget then you wouldn’t need anything between the [] in the Item metadata.

Thanks but i tried

title: =items[props.item].label

but then the title is blank.

Then I guess you can’t get the label that way.

Luckily I can restore some of the posts from my email that were lost during the failed upgrade this weekend. I did lose some examples in the OP so I’ll need to restore those as well.


@c_r posted:

Great examples! Thats how far I got with custom List items as well.

Whats strange is that when you add such a custom widget to a page, you can’t edit the widget properties anymore (in visual edit mode), but instead you can only edit the settings of the (underlying) standard oh-list-item (with the configs set in the widget).

Any idea how this you be changed? I can only get it to work in textual configuration.

Widet Properties:

image|autoxauto

Properties when putting the widget on a page:

image|autoxauto


My reply:

I don’t know what you mean specifically about adding them to a page. If you are just adding these to a page as is, that’s probably the problem. These are List Item Widgets. They are not stand alone widgets. They have to be contained by some other widget, such as a Card or a Cell widget. They do not work on their own and that is why they do not render a preview on the custom widget page.


@alfista2600 posted

Thanks for these, Rich. I’ve implemented a few already.

Follow up question: Is there any way to put the Equipment name in the footer of these widgets? Or some type of custom metadata?

When I look at a list of items, they are all named, as example ‘Battery Level’, for when I look at the list of points associated with the equipment. It is ugly to see ‘Equipment Name - Battery Level’ in that view.


My response:

You can customize these how ever you want. But you’ll probably want to add a property to set the Item that represents the equipment and then reference that property.

Personally, I always make sure to give my Items unique labels in addition to Item names so that no matter where the Item is listed (in the model, in the Items settings, etc.) you can always tell what the Item refers to. In other words, the problem is bigger than just the Properties tab of the overview page so I recommend adding the equipment name to the Item’s label instead.


@Malti1812 posted

Hello, I am unfortunately not receiving any data from
action: analyzer. No data analysis is opened.
Data comes from Influxdb


My reply:
Open a new thread to ask for help on that one. There are a number of things that can be wrong and figuring out what is off topic for this thread. All I’ll say on the topic is to make sure all the Items are being saved and make sure InfluxDB is set as the default.


@stefan13

Hello @rlkoshak,
I use

color: '=(Number.parseInt(items[props.Rooms_1 + "_CO2Gehalt"].state) > 800) ? "red" : "gray"'

to get a conditional text color in my widget.
However, for unknown reason the expression is always “false”, hence the text is in gray color.

The state is usually with a Unit “ppm” but due to Number.parseInt the unit is stripped.
I double checked this with Widget Expression Tester and it works fine.

However the condition doesn’t work as expected. Any idea what I did wrong?

Thanks a lot

Stefan


My reply:

There is not enough information to begin to help. All I can recommend is to make sure the props.Rooms_1 is set properly. Double check the state of the Item. Experiment.


@Andrew_Pawelski posted

@c_r I have the same - doesnt seem to allow changes to any variables - oddly, even adding them in the config YAML they actually disappear after saving and going to the run mode.

Ive also noticed the widget not being refreshed - this might be related. When I noticed there were no variables, I hard coded where =props.title would have been and it will not show the updated widget.


My response, see above. The List Widget must be in the slot of some parent container widget. It cannot stand on it’s own.

1 Like

Hi Rick, I have added the widget as a list-item to a list-card. I simply clicked on the “+” sign in the list card and then selected the widget instead of e.g. a regular label item. You may be able to see it in the background in the second screenshot.

I have made the same observation that the widget/list items often disappears from the list and does not keep e.g. the item which was selected in the widget/list item configuration after saving and reloading the page.

I’ve not tried to use these widgets in this way nor have I see similar behavior with the list. All I can recommend is to file an issue.