A couple of simple oh-repeater examples

Thanks Justin. That is actually really nice.

I could not get the location. Is that because the item related to equipment instead of directly within a location?

Yes. The semantic tags do not propagate down the hierarchy so hasLocation only works for equipment not points.

In some cases you may want to add some points to the location group directly, in addition to the equipment. For instance adding a temperature measurement to a room location, because it represents the temperature in the room.

Am I going mad? I can’t seem to search more than one itemTag at a time.

I type itemTags: Smartphone and all Smartphone tagged items are found. But the moment I add a second term I get 0 results itemTags: Smartphone,Smartwatch

All of the examples above that use more than one term just seperate with a comma, but this just isn’t working for me

The array in itemTags is treated as AND. You cannot search for Smartphone OR Smartwatch, but you can search for Switch AND Light or Door AND Status.

Ahhh…
secrets.

Wonder why this simple info isn’t in the docs?

Is there a way to do OR?

This isn’t really a choice of the UI design, it comes directly from the API; that’s how the API call to fetch items works. That said, this question does come up once in a blue moon and may be worth adding to the docs.

Yes, but…

You can get the repeater to return a complete list of all the items and then use the repeater filter property to get only tag A OR tag B. The ‘but’ here is that that’s going to be somewhat process intensive and if you have to do it more than a few times on a UI page, you’re definitely going to see a slow down.

The better solution here is just to add another custom tag to these items, PersonalDevice or some such and then use that in the repeater. Yeah, it’s one small extra step, but it results in more direct control of which items your repeater is delivering and, although I don’t know your system, I’m going to guess that these items don’t change or get added and removed often enough for this to be a particular hardship from an administrative standpoint.

2 Likes

Thanks. You always give very good answers.

No idea if I can post it here, but for some reason my icons are not dynamic anymore in my oh-repeater

Code:

- component: oh-repeater
            config:
              for: item
              fragement: true
              groupItem: Blinds
              sourceType: itemsInGroup
            slots:
              default:
                - component: oh-rollershutter-item
                  config:
                    icon: oh:rollershutter
                    item: =loop.item.name
                    title: =loop.item.label

And this as result:

Which looks good enough except that my icon is not showing the correct state, for example if I check it in the Overview>Location it looks like this:
image

here it is clearly closed, tried finding on the forums why it does this but can’t find what im doing wrong.

When using an OH icon there is a second parameter to indicate if the icon is dynamic or not (in the UI it’s called “Icon depends on state” but I’m not sure what the actual name of the field is. From a quick scan of the reference docs it looks like it might just be state.

For OH icons the state parameter lets you manually set a state which the icon will respond to (which can of course just be set to the dynamic state of an item).

For the family of list item components, such as the oh-rollershutter-item the parameter to use is iconUseState which you just set to true if you want the icon to respond to the state of the item that the component is bound to.

2 Likes

when i add this widget and save the page, the widget gets reset?

Hello Rick,
I am trying to make a generic selection widget and I am having a problem when passing an props.item to the repeater.
Maybe you have an idea.
This is what I want to achieve:


When clicking the box this popup shows up:

The radio stations are number items:

String SonosPlay3Essen_Tuneinstationid          (gSonos) {
	channel="sonos:PLAY3:RINCON_5CAAFD5AB44801400:tuneinstationid",
        stateDescription=""[
                pattern="%d",
                options="
                        15439=Radio Aargovia,
                        17465=SRF1,
                        24862=SRF3,
                        57881=Radio Fantasy,
                        96745=Antenne Bayern Chillout,
                        214040=Charivari LOUNGE,
                        2591=SomaFM-Groove-Salad,
                        42828=Deutschlandfunk,
                        120806=Deutschlandfunk Nova,
                        42824=Antenne Bayern
                        "
        ]
}

The widget code for the button is (the item is hard coded to SonosPlay3Bad_Tuneinstationid):

          - component: oh-repeater
            config:
              for: selection
              fragment: true
              in:
                - icon: f7:hifispeaker
                  item: SonosPlay3Bad_Tuneinstationid
              sourceType: array
            slots:
              default:
                - component: f7-col
                  slots:
                    default:
                      - component: oh-list
                        config:
                          id: list
                        slots:
                          default:
                            - component: oh-list-item
                              config:
                                after: =items[loop.selection.item].displayState
                                icon: =loop.selection.icon
                                iconColor: default
                                popupOpen: =".selectionPopupBad_"+loop.selection_idx
                                smartSelect: true
                                style:
                                  border: 1px solid lightgray
                                  border-radius: 5px
                                title: =loop.selection.title

and for the popup window:

                      - component: f7-popup
                        config:
                          class: ="selectionPopupBad_"+loop.selection_idx
                        slots:
                          default:
                            - component: f7-page
                              slots:
                                default:
                                  - component: f7-navbar
                                    config:
                                      style:
                                        position: sticky
                                      title: =loop.selection.title
                                    slots:
                                      left:
                                        - component: oh-link
                                          config:
                                            iconAurora: f7:arrow_left
                                            iconIos: f7:arrow_left
                                            iconMd: material:arrow_back
                                            popup-close: true
                                  - component: f7-list
                                    config:
                                      virtualList: true
                                    slots:
                                      default:
                                        - component: oh-repeater
                                          config:
                                            for: option
                                            fragment: true
                                            itemOptions: =loop.selection.item
                                            sourceType: itemStateOptions
                                          slots:
                                            default:
                                              - component: oh-list-item
                                                config:
                                                  action: command
                                                  actionCommand: =loop.option.value
                                                  actionFeedback: ='{ "text":"You selected <b>' + loop.option.label + '</b><br>Sending command <b>' +  loop.option.value + "to item " + loop.selection.item  + '</b>", "position":"center","icon":"<i style=\\"color:green\\" class=\\"f7-icons\\">checkmark_alt</i>","closeButton":true }'
                                                  actionItem: =loop.selection.item
                                                  checked: "=loop.option.value === items[loop.selection.item].state ? true : false"
                                                  noChevron: true
                                                  popupClose: true
                                                  radio: true
                                                  title: =loop.option.label

Right now I have 4 selection widgets but to clean up the code I want to have one for all 4 items.
The problem is here:
item: SonosPlay3Bad_Tuneinstationid
when using this:
item: =items[props.ItemTuneInStationId]

It doesn’t work. Here ItemTuneInStationId is given by the widget configuration

Unfortunately the extent of my knowledge on UI widgets is on display above. I’ve not really messed with options before except very basically in a List Item Widget and even then I didn’t do much more than see that it works, but that was a totally different base widget and use case.

I don’t really have any great ideas but suggest you post a new thread so people who are better at widgets than I am might see it.

The only general thing I can think of is I often need to put expressions into double quotes so you might try

item: "=items[props.ItemTuneInStationId]"

Here you are setting the value of item to a string of the item name that you want, which is correct.

Here you are setting the value of item to an object with state, displayState, and type (depending on OH version) keys. This is not the same thing.

props.ItemTuneInStationId is already a string. You don’t need to do anything to it just pass it directly to the item property.

item: =props.ItemTuneInStationId
2 Likes

Justin this was it, thank you for the hint.
I have now a generic selection widget:

uid: select
tags:
  - Custom
props:
  parameters:
    - context: item
      description: Selection Item with State Descirption
      label: Selection Item
      name: itemSelect
      required: true
      type: TEXT
    - context: text
      label: Icon
      name: icon
      required: false
      type: TEXT
  parameterGroups: []
timestamp: Sep 15, 2023, 11:35:07 PM
component: oh-repeater
config:
  for: selection
  fragment: true
  in:
    - icon: =props.icon
      item: =props.itemSelect
  sourceType: array
slots:
  default:
    - component: f7-col
      slots:
        default:
          - component: oh-list
            config:
              id: list
            slots:
              default:
                - component: oh-list-item
                  config:
                    after: =items[loop.selection.item].displayState
                    icon: =loop.selection.icon
                    iconColor: default
                    popupOpen: =".selectionPopup_" + props.itemSelect + loop.selection_idx
                    smartSelect: true
                    style:
                      border: 1px solid lightgray
                      border-radius: 5px
                      margin-left: 10px
                      margin-right: 10px
                      margin-top: 10px
                    title: =loop.selection.title
          - component: f7-popup
            config:
              class: ="selectionPopup_" + props.itemSelect + loop.selection_idx
            slots:
              default:
                - component: f7-page
                  slots:
                    default:
                      - component: f7-navbar
                        config:
                          style:
                            position: sticky
                          title: =loop.selection.title
                        slots:
                          left:
                            - component: oh-link
                              config:
                                iconAurora: f7:arrow_left
                                iconIos: f7:arrow_left
                                iconMd: material:arrow_back
                                popup-close: true
                      - component: f7-list
                        config:
                          virtualList: true
                        slots:
                          default:
                            - component: oh-repeater
                              config:
                                for: option
                                fragment: true
                                itemOptions: =loop.selection.item
                                sourceType: itemStateOptions
                              slots:
                                default:
                                  - component: oh-list-item
                                    config:
                                      action: command
                                      actionCommand: =loop.option.value
                                      actionFeedback: ='{ "text":"You selected <b>' + loop.option.label + '</b><br>Sending command <b>' +  loop.option.value + '</b> to item", "position":"center","icon":"<i style=\\"color:green\\" class=\\"f7-icons\\">checkmark_alt</i>","closeButton":true }'
                                      actionItem: =loop.selection.item
                                      checked: "=loop.option.value === items[loop.selection.item].state ? true : false"
                                      noChevron: true
                                      popupClose: true
                                      radio: true
                                      title: =loop.option.label

which can than be included in other widgets, e.g.:

uid: radiostation-select
tags: []
props:
  parameters:
    - label: title
      name: vTitel
      required: false
      type: TEXT
    - context: item
      description: Sonos tuneinstationid item
      label: ItemTuneInStationId
      name: ItemTuneInStationId
      required: true
      type: TEXT
  parameterGroups: []
timestamp: Sep 15, 2023, 11:57:47 PM
component: f7-card
config:
  style:
    border-radius: var(--f7-card-expandable-border-radius)
    box-shadow: 5px 5px 10px 1px rgba(0,0,0,0.1)
    height: 110px
    noShadow: false
    width: 350px
  title: =props.vTitel
slots:
  default:
    - component: widget:select
      config:
        itemSelect: =props.ItemTuneInStationId
        icon: f7:hifispeaker

Resulting in:

So the code is now much better than before as I had the selection code in many widgets.

I tried to extend the example from @rlkoshak at the beginning of the thread with the switch for the group. No matter how I try to set it up, the outcome always looks weird. any ideas ?

uid: all_lights
tags:
  - card
  - lights
props:
  parameters:
    - description: A text prop
      label: Card title
      name: title
      required: false
      type: TEXT
    - context: item
      description: An item to control
      label: Item
      name: lightgroup
      required: false
      type: TEXT
  parameterGroups: []
timestamp: Jan 22, 2024, 5:34:39 PM

component: f7-card
config:
  title: =props.title
slots:
  default:
    - component: oh-toggle-item
      config:
        item: =props.lightgroup
        icon: f7:lightbulb
        title: =props.lightgroup
    - component: oh-list
      slots:
        default:
          - component: oh-repeater
            config:
              for: item
              sourceType: itemsInGroup
              groupItem: =props.lightgroup
              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") ? "green" : "gray"'
                    title: =loop.item.label
                    item: =loop.item.name

It will help you to understand if you dig a little deeper into the different types of components:

Especially relevant is this line:

  • List Item: a component placed inside a list type container meant only to be displayed as part of a list and which will not display properly on its own (e.g., oh-slider-item)

Thanks @JustinG this worked. Thus I am still trying to find out why I can access .state but not .displayState of items[props.lightgroup] in the title

uid: all_lights
tags:
  - card
  - lights
props:
  parameters:
    - description: A text prop
      label: Card title
      name: title
      required: false
      type: TEXT
    - context: item
      description: An item to control
      label: Item
      name: lightgroup
      required: false
      type: TEXT
  parameterGroups: []
timestamp: Jan 22, 2024, 5:34:39 PM

component: f7-card
config:
  title: =props.title
slots:
  default:
    - component: f7-list
      config:
        virtualList: true
      slots:
        default:
          - component: oh-toggle-item
            config:
              item: =props.lightgroup
      
              icon: f7:lightbulb
              title: =items[props.lightgroup].state
              iconColor: '=(items[props.lightgroup].state == "ON") ? "yellow" : "gray"'
              label: as
              color: '=(items[props.lightgroup].state == "ON") ? "green" : "gray"'
          - component: oh-repeater
            config:
              for: item
              sourceType: itemsInGroup
              groupItem: =props.lightgroup
              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") ? "green" : "gray"'
                    title: =loop.item.label
                    item: =loop.item.name