Scene Config Widget YAML - oh-repeater, row formatting, f7-list-input

Hi,

I am working on a Scene Config UI inspired by this widget

I haven’t started any of the metadata and var stuff yet, I am still trying to use repeaters and filters to dynamically populate a UI first.
I will repeat this for Heating, Alarm, and other stuff if I can get this working.

At the top there will be basic controls for selecting, creating, deleting, and resetting scenes.

then accordion open the lighting

There can be a few single, hardcoded items, then the lights are loaded dynamically using oh-repeater, and then each light has it’s properties loaded using a second repeater inside an accordion. There will be an input control, buttons to store and clear values, and a badge to show the stored value

The problems I am running into:

Setting an appropriate control for each property -
Originally I thought I could use an expression in the ‘component’ field to set oh-toggle-item, oh-stepper-item etc, but this doesn’t work. It seems you can’t use an expression here.
My current version is using the f7-list-input component which does allow me to use an expression in the ‘type’ field so I can set a different input control for each property type.

How can I format and set options for these f7 components?
How can I populate the dropdown menu for the ‘select’ type?
How can I set min, max, and show labels for ‘range’ type?
How can I format the range slider and other input boxes to fit properly? I’m using a forced width of x% to make this illustration fit, but this doesn’t seem like the right way to do it to scale properly across devices.
I’ve seen the f7 docs, but it’s not in YAML.

Is there a better way to do this?

And formatting components in a row.
Can anyone tell me how to format the rows shown here:

You can see how I did this in the YAML below, but I’m not doing it right.
Each row should be properly spaced and lined up neatly with all the rows beneath, and It needs to have more space to interact with the input controls if using on a phone.
Maybe STORE and CLEAR could be stacked on top of each other, and maybe the badges should be center justified? Or have two rows for each property? Any advice on row formatting would be appreciated.

Where can I find a list of available classes?
I keep seeing things like this in examples in forums -

class:
  - align-items-center
  - display-flex

But I don’t know where they come from, what is available, or what a lot of them actually mean. But I suspect they could be useful for something like this.

EXAMPLE CODE

Items

    Group BackHall_Ceiling_Light "Ceiling Light" <lightbulb> (BackHall, BackHall_MotionLightSensor_AssociatedLights) ["Lightbulb"] {
            homekit="Lighting.Name"
        }
        Dimmer BackHall_Ceiling_Light_Brightness "Brightness [%.0f%%]" <slider> (BackHall_Ceiling_Light, gAll_Lights_Brightness, gAll_Lights_OnOff) ["Control", "Light", "Config"] {
            channel="deconz:extendedcolorlight:00212E064C59:00158d0003e4425501:color", 
            widgetOrder="02",
            homekit="Lighting, Lighting.Brightness"
        }
        Dimmer BackHall_Ceiling_Light_SceneBrightness "Scene Brightness [%.0f%%]" <slider> (BackHall_Ceiling_Light, gAll_Lights_SceneBrightness) ["Setpoint", "Light", "Config"] {
            widgetOrder="03"
        }
        Number BackHall_Ceiling_Light_ColorTemperature "Color Temperature [%.0f K]" <colorlight> (BackHall_Ceiling_Light, gAll_Lights_ColorTemperature) ["Control", "ColorTemperature"] {
            channel="deconz:extendedcolorlight:00212E064C59:00158d0003e4425501:color_temperature",
            stateDescription=" "[
                pattern="%.0f K"
            ],
            widgetOrder="04",
            widget="widget:defaultWidget_light_colorTemperature",
            listWidget="widget:defaultListWidget_light_colorTemperature"
        }
        Switch BackHall_Ceiling_Light_ColorMode "Color Mode" <colorlight> (BackHall_Ceiling_Light, gAll_Lights_ColorMode) ["Setpoint", "Light", "Config"] {
            widgetOrder="05",
            stateDescription=" "[
                options="ON=RGB, OFF=WHITE"
            ],
            widget="widget:defaultWidget_light_colorMode",
            listWidget="widget:defaultListWidget_light_colorMode"
        }
        Color BackHall_Ceiling_Light_Color "Color" <colorlight> (BackHall_Ceiling_Light, gAll_Lights_Color) ["Setpoint", "Light", "Config"] {
            channel="deconz:extendedcolorlight:00212E064C59:00158d0003e4425501:color",
            widgetOrder="06",
            listWidget="widget:defaultListWidget_light_color"
        }
        Number:Illuminance BackHall_Ceiling_Light_IlluminanceThreshold "Illuminance Threshold [%.0f lx]" <qualityofservice> (BackHall_Ceiling_Light, gAll_Lights_IlluminanceThreshold) ["Setpoint", "Light", "Config"] {
            widgetOrder="07",
            widget="widget:defaultWidget_light_illuminanceThreshold",
            listWidget="widget:defaultListWidget_light_illuminanceThreshold"
        }
        Switch BackHall_Ceiling_Light_MotionOnOff "Motion On/Off" <switch> (BackHall_Ceiling_Light, gAll_Lights_MotionOnOff) ["Setpoint", "Light", "Config"] {
            widgetOrder="08"
        }

        Number BackHall_Ceiling_Light_MotionTimer "Motion Timer [%.0f mins]" <time> (BackHall_Ceiling_Light, gAll_Lights_MotionTimer) ["Setpoint", "Duration", "Config"] {
            widgetOrder="09",
            widget="widget:defaultWidget_light_motionTimer",
            listWidget="widget:defaultListWidget_light_motionTimer"
        }
        Number BackHall_Ceiling_Light_OnTime "Auto Off Timer [%.0f mins]" <time> (BackHall_Ceiling_Light, gAll_Lights_OnTime) ["Setpoint", "Duration", "Config"] {
            widgetOrder="10",
            widget="widget:defaultWidget_light_onTime",
            listWidget="widget:defaultListWidget_light_onTime"
        }
        String BackHall_Ceiling_Light_Alert "Alert" <alarm> (BackHall_Ceiling_Light, gAll_Lights_Alert) ["Setpoint", "Light", "Config"] {
            channel="deconz:extendedcolorlight:00212E064C59:00158d0003e4425501:alert", 
            widgetOrder="11",
            stateDescription=" "[
                options="none=None, select=Short Flash, lselect=Long Flash"
            ],
            widget="widget:defaultWidget_light_alert",
            listWidget="widget:defaultListWidget_light_alert"
        }

Widget YAML

uid: sceneConfigExample
tags: []
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: Jul 20, 2022, 7:26:33 AM
component: f7-block
slots:
  default:

    - component: f7-card
      config:
        style:
          border-radius: 20px
          margin-bottom: 40px
        themeDark: false
        title: Scene Configuration
      slots:
        default:
          - component: f7-list
            config:
              accordionList: true
            slots:
              default:
                - component: oh-list-item # The current scene
                  config:
                    action: options
                    actionItem: Scenes_Selection
                    badge: =items.Scenes_Selection.state
                    icon: f7:photo
                    iconColor: green
                    title: Current Scene
                - component: oh-list-item # To be wired up as the scene to edit
                  config:
                    badge: =items.Scenes_Selection.state # To be changed, for illustration only
                    icon: f7:photo_on_rectangle
                    iconColor: blue
                    title: Selected Scene to Edit
                - component: oh-list-item # To be wired up as the scene to edit
                  config:
                    icon: f7:plus_circle
                    iconColor: red
                    title: New Scene
                - component: oh-list-item # To be wired up as the scene to edit
                  config:
                    icon: f7:arrow_counterclockwise_circle
                    iconColor: red
                    title: Reset Scene   
                - component: oh-list-item # To be wired up as the scene to edit
                  config:
                    icon: f7:minus_circle
                    iconColor: red
                    title: Delete Scene     
                
    - component: f7-card
      config:
        style:
          border-radius: 20px
          margin-bottom: 40px
      slots:
        default:
          - component: f7-list
            config:
              accordionList: true
            slots:
              default:
                - component: oh-list-item
                  config:
                    title: Lighting
                    icon: f7:lightbulb
                    iconColor: yellow
                  slots:
                    accordion:
                      - component: f7-list
                        config:
                          accordionList: true
                          style:
                            margin-left: 15px
                        slots:
                          default:
                            - component: oh-toggle-item # To be wired up. For illustraion only
                              config:
                                title: Some global light setting
                                icon: oh:switch
                            - component: oh-stepper-item # To be wired up. For illustraion only
                              config:
                                title: Another global light setting
                                icon: oh:rgb    
                            - component: oh-repeater # Get all lights
                              config:
                                fetchMetadata: semantics
                                for: light
                                itemTags: lightbulb
                                sourceType: itemsWithTags
                                accordionList: true
                              slots:
                                default:
                                  - component: oh-list-item
                                    config:
                                      icon: =loop.light.category
                                      item: =loop.light.name
                                      title: =loop.light.name.replaceAll("_", " ")
                                      
                                    slots:
                                      accordion:
                                        - component: f7-list-item
                                          config:
                                            style:
                                              margin-left: 20px
                                              margin-bottom: 30px
                                          slots:
                                            default:
                                              - component: oh-repeater # Get all properties for the light that have a metadata tag 'Config'
                                                config:
                                                  fetchMetadata: semantics
                                                  for: property
                                                  groupItem: =loop.light.name
                                                  sourceType: itemsInGroup
                                                  filter: loop.property.tags.includes("Config")
                                                  accordionList: true
                                                slots:
                                                  default:
                                                    - component: f7-row
                                                      config:
                                                        class:
                                                          - align-items-center
                                                          - display-flex
                                                      slots:
                                                        default:
                                                          - component: oh-icon
                                                            config:
                                                              icon: =loop.property.category
                                                              style:
                                                                height: 30px
                                                                font-size: 20px
                                                          - component: f7-list-input # Use expressions to load appropriate input controls and settings for each type of property
                                                            config:
                                                              type: '=(loop.property.label == "Alert") ? "select" : (loop.property.label == "Auto Off Timer") ? "number" : (loop.property.label == "Brightness") ? "range" : (loop.property.label == "Color") ? "colorpicker" : (loop.property.label == "Color Mode") ? "select" : (loop.property.label == "Illuminance Threshold") ? "range" : (loop.property.label == "Motion On/Off") ? "select" : (loop.property.label == "Motion Timer") ? "number" : (loop.property.label == "Scene Brightness") ? "range" : "text"'
                                                              item: =loop.property.name
                                                              value: =items[loop.property.name].state
                                                              outline: true
                                                              min: 0
                                                              max: 100
                                                              placeholder: =items[loop.property.name].state
                                                              floating-label: true
                                                              label: =loop.property.label
                                                              style: 
                                                                width: 30%

                                                          - component: f7-list-button # To be wired  up for storing value to metadata
                                                            config:
                                                              title: STORE 
                                                          - component: f7-list-button # To be wired  up for clearing value from metadata
                                                            config:
                                                              title: CLEAR
                                                          - component: f7-list-item # To be wired up to the stored value. For illustration only
                                                            config:
                                                              badge: =items[loop.property.name].state
                                                              badge-color: green # Green if a value is stored, grey if there is no value stored

That’s been a known limitation for a while. There are various solutions, the input type expression that you found is one good one. There is also the possibility to just create multiple widgets and use the visibility property to only show the one that matches the desired type. This as the advantage of avoiding the extremely long nested expression you’ve developed for the input type, but has the disadvantage of make the overall code a little longer (and not rendering as well in the UI page editor, which is a very minor issue).

You are going to run into a few problems, I suspect, because you are using the f7 input. The f7 components expect you to be able to have underlying javascript functions for their operation, but you just can’t provide that in the OH yaml. What this means is that getting access to the value that been input into an f7-input-list is technically difficult. This is why there are OH specific version of nearly all the f7 components, those OH version have the necessary js under the hood and offer the the OH specific properties for linking to item states or variables.

Many of the basic formatting options are covered by the f7 css variables that are listed in the f7 docs.

To my knowledge, there isn’t a way to do this at the moment. The way the yaml is converted into the appropriate vue code for the f7 components you cannot incorperate the required <select> elements into the input component. Several people have tried but I haven’t seen anyone succeed yet.

For most of the properties listed in the f7 docs, you should just be able to include those as properties of in the config section. That section gets passed directly to the f7 element. The only caveat is that for multi-word properties (those that have a “-” in the name) you use camelcase instead. For example: format-label becomes formatLabel.