[OH3] Main UI - New „main_widget“ - development and testing [deprecated]

@Nic0205 You already have the image!
Option a: classic text menu under Home OR
Option b. Tab bar

Well noted. Thank you.
@JustinG @Nic0205 @rubenfuser Gentlemen, may I have your feedback?

Let me check tonight, might have a longer coding session after kid is gone to bed…

Ah dismissed the picture. I vote for tabbar!

For me it’s the same. ‘Cause the actual mode for me it’s not so user friendly,i vote for no bottom menu, because i’m curious of how will be new mode of navigating :slight_smile:

The stylesheet property is not processed by the expression parser, so things like props.textColor won’t be replaced with values, they’re just sent to the css as is, and css has no idea what props.textColor means. If you want to have values in the stylesheet that are dynamic you have to do what I demonstrated with the text color for the unselected options. You have to define a css variable in the style object, which is processed by the expression parser:

  style:
    display: flex
    flex-direction: column
    height: calc(100vh - var(--f7-toolbar-height) - var(--f7-safe-area-bottom) - var(--f7-safe-area-top))
    justify-content: space-between
    margin: 0px
    padding: 0px
    --opmw-menu-text-color: '=(themeOptions.dark=="light")?("#8C8C8C"):("#848484")'

And then in the stylesheet you can refer to the value of that variable:

    .unselected_menu_item {
      color: var(--opmw-menu-text-color);
    }

You’re never really going to manage a rules creation/editing page just through custom widgets. It is technically feasible, but the complexity required would many orders of magnitude higher than what you’re doing right now and would only replicate what is already available through the rules page. Really there are only two sensible options for incorporating some sort of “rules” section:

  1. just have that button take the user to the MainUI rules page
  2. Allow a configuration where the user adds switch items to the conditions of certain rules and tags those items a certain way. Then your “rules” page could be a list of those toggle switches allowing the user easy access to enabling or disabling the activity of those particular rules.

I was just thinking that would be nice if you can enable/ disable rules (and not editing or creating new one!!s). And yes, a link to OH rules page seems a very good idea.

@Nic0205 @hmerk @rubenfuser So, our milestone is this:

Home menu: sub menu would be only the tab bar on footer
Floors menu: Sub menu on header and tab bar for filtering
Room menu: Sub menu on header and tab bar for filtering

Befor @hmerk and @Nic0205 starts firing up, ithat would be graet if I have your approval.

To be honest I’m quite understand what you mean…

Absolutely not, as you need admin rights for that!

Ahh - I see. thank you works like a charm now - but only after pressing one of the menu buttons once.
Until pressing a button the color is red / dark orange. It seems that the stylesheet takes effect after clicking/ performing the action and not direct after loading the widget…

I cannot see where this red is defined in the code - could you have a quick review on it?

EDIT: The color is “#E64A19” and this is the css variable var(--f7-button-text-color,var(--f7-theme-color))

EDIT2: tried it this way and it works (code is updated):

    --f7-button-text-color: "#8c8c8c"

But don’t know if this is a good idea…

How could I define not to use this but the css defined in the widget…?

uid: main_widget
tags: []
props:
  parameters:
    - default: black
      description: Set default color for Text
      label: Text color
      name: textColor
      required: false
      type: TEXT
    - default: RGB(96, 96, 96)
      description: Set default color for Text
      label: Bottom-Navbar-Color
      name: bnavColor
      required: false
      type: TEXT
    - default: Somewhere
      description: Name for your weather location
      label: Weather Location
      name: locationTitle
      required: false
      type: TEXT
    - context: item
      description: Name of scenes group item
      label: Scenes Group
      name: scenesGroup
      required: false
      type: TEXT
    - context: item
      description: Name of security group item
      label: Security Group
      name: securityGroup
      required: false
      type: TEXT
    - context: item
      description: Security Mode Item
      label: Security Mode
      name: securityMode
      required: true
      type: TEXT
  parameterGroups: []
timestamp: Sep 24, 2022, 6:59:04 PM
component: f7-block
config:
  style:
    display: flex
    flex-direction: column
    height: calc(100vh - var(--f7-toolbar-height) - var(--f7-safe-area-bottom) - var(--f7-safe-area-top))
    justify-content: space-between
    margin: 0
    padding: 0
    widht: 100vh
    --menu-text-color: =props.textColor
    --f7-button-text-color: "#8c8c8c"
  stylesheet: >
    .selected_menu_item {
      color: var(--menu-text-color);
      
      font-weight: bold;
      text-decoration-color: #F8BB00 !important;
      text-decoration: underline;
      text-underline-offset: 2.px;     
    }


    .unselected_menu_item {
      color: #8C8C8C;
    } .chevron {
      color: #F8BB00;
    }    
slots:
  default:
    - component: f7-block
      config:
        style:
          flex: 0 0 auto
          overflow: scroll
      slots:
        default:
          - component: f7-segmented
            config:
              style:
                flex: 1 1 auto
            slots:
              default:
                - component: oh-repeater
                  config:
                    for: baseMenu
                    fragment: true
                    in:
                      - name: Home
                      - name: Floors
                      - name: Rooms
                    map: loop.baseMenu.name
                    sourceType: array
                  slots:
                    default:
                      - component: oh-button
                        config:
                          action: variable
                          actionVariable: objVar
                          actionVariableValue:
                            selectSection: ="SECTION" + loop.baseMenu_idx
                          class: '=(vars.objVar.selectSection=="SECTION" + loop.baseMenu_idx) ? "selected_menu_item" : "unselected_menu_item"'
                          style:
                            font-size: 28px
                            font-weight: 200
                          text: =loop.baseMenu
          - component: f7-row
            config:
              style:
                align-items: center
                display: flex
                flex-direction: row
                flex-wrap: nowrap
                height: 2em
                justify-content: space-between
                width: 100%
              visible: false
            slots:
              default:
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: buttonIndexHome
                    actionVariableValue: =(vars.buttonIndexHome || 0) - 1
                    iconF7: chevron_left
                    class: chevron
                    style:
                      flex: 0 0 auto
                      height: 2em
                - component: oh-repeater
                  config:
                    fetchMetadata: widgetOrder
                    for: menuArray
                    fragment: true
                    itemTags: Floor
                    map: loop.menuArray_source
                    sourceType: itemsWithTags
                  slots:
                    default:
                      - component: f7-row
                        config:
                          style:
                            display: flex
                            height: 2em
                            justify-content: center
                            overflow: hidden
                        slots:
                          default:
                            - component: oh-repeater
                              config:
                                filter: loop.menuArray_idx == 0
                                for: menuButtonHome
                                fragment: true
                                in: =loop.menuArray
                                map: ((loop.menuButtonHome.metadata && loop.menuButtonHome.metadata.widgetOrder && loop.menuButtonHome.metadata.widgetOrder.value) || 0).toString().padStart(3,'0') + '&' + loop.menuButtonHome_idx
                              slots:
                                default:
                                  - component: oh-button
                                    config:
                                      action: variable
                                      actionVariable: floor
                                      actionVariableValue: =loop.menuArray[loop.menuButtonHome_source.sort()[loop.menuButtonHome_idx].split('&')[1]].name
                                      style:
                                        flex: 0 0 auto
                                        height: 2em
                                        order: =(((vars.buttonIndexHome || 0) % loop.menuButtonHome_source.length) + loop.menuButtonHome_source.length + loop.menuButtonHome_idx) % loop.menuButtonHome_source.length
                                      text: =loop.menuArray[loop.menuButtonHome_source.sort()[loop.menuButtonHome_idx].split('&')[1]].label
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: buttonIndexHome
                    actionVariableValue: =(vars.buttonIndexHome || 0) + 1
                    iconF7: chevron_right
                    class: chevron
                    style:
                      flex: 0 0 auto
                      height: 2em
          - component: f7-row
            config:
              style:
                align-items: center
                display: flex
                flex-direction: row
                flex-wrap: nowrap
                height: 2em
                justify-content: center
                width: 100%
              visible: '=vars.objVar ? (vars.objVar.selectSection=="SECTION1") ? true : false : false'
            slots:
              default:
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: buttonIndexFloor
                    actionVariableValue: =(vars.buttonIndexFloor || 0) - 1
                    iconF7: chevron_left
                    class: chevron
                    style:
                      flex: 0 0 auto
                      height: 2em
                - component: oh-repeater
                  config:
                    fetchMetadata: widgetOrder
                    for: menuArray
                    fragment: true
                    itemTags: Floor
                    map: loop.menuArray_source
                    sourceType: itemsWithTags
                  slots:
                    default:
                      - component: f7-row
                        config:
                          style:
                            display: flex
                            height: 2em
                            justify-content: center
                            overflow: hidden
                        slots:
                          default:
                            - component: oh-repeater
                              config:
                                filter: loop.menuArray_idx == 0
                                for: menuButtonFloor
                                fragment: true
                                in: =loop.menuArray
                                map: ((loop.menuButtonFloor.metadata && loop.menuButtonFloor.metadata.widgetOrder && loop.menuButtonFloor.metadata.widgetOrder.value) || 0).toString().padStart(3,'0') + '&' + loop.menuButtonFloor_idx
                              slots:
                                default:
                                  - component: oh-button
                                    config:
                                      action: variable
                                      actionVariable: floor
                                      actionVariableValue: =loop.menuArray[loop.menuButtonFloor_source.sort()[loop.menuButtonFloor_idx].split('&')[1]].name
                                      style:
                                        color: '=vars.floor ==(loop.menuArray[loop.menuButtonFloor_source.sort()[loop.menuButtonFloor_idx].split("&")[1]].name) ? textColor : "#8C8C8C"'
                                        flex: 0 0 auto
                                        height: 2em
                                        order: =(((vars.buttonIndexFloor || 0) % loop.menuButtonFloor_source.length) + loop.menuButtonFloor_source.length + loop.menuButtonFloor_idx) % loop.menuButtonFloor_source.length
                                        text-decoration: underline
                                        text-decoration-color: '=vars.floor ==(loop.menuArray[loop.menuButtonFloor_source.sort()[loop.menuButtonFloor_idx].split("&")[1]].name) ? "#F8BB00" : "transparent"'
                                        text-underline-offset: 4px
                                      text: =loop.menuArray[loop.menuButtonFloor_source.sort()[loop.menuButtonFloor_idx].split('&')[1]].label
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: buttonIndexFloor
                    actionVariableValue: =(vars.buttonIndexFloor || 0) + 1
                    iconF7: chevron_right
                    class: chevron
                    style:
                      flex: 0 0 auto
                      height: 2em
          - component: f7-row
            config:
              style:
                align-items: center
                display: flex
                flex-direction: row
                flex-wrap: nowrap
                height: 2em
                justify-content: center
                width: 100%
              visible: '=vars.objVar ? (vars.objVar.selectSection=="SECTION2") ? true : false : false'
            slots:
              default:
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: buttonIndexRoom
                    actionVariableValue: =(vars.buttonIndexRoom || 0) - 1
                    iconF7: chevron_left
                    style:
                      color: "#F8BB00"
                      flex: 0 0 auto
                      height: 2em
                - component: oh-repeater
                  config:
                    fetchMetadata: widgetOrder
                    for: menuArrayRoom
                    fragment: true
                    itemTags: =vars.floor
                    map: loop.menuArrayRoom_source
                    sourceType: itemsWithTags
                  slots:
                    default:
                      - component: f7-row
                        config:
                          style:
                            display: flex
                            height: 2em
                            justify-content: center
                            overflow: hidden
                        slots:
                          default:
                            - component: oh-repeater
                              config:
                                filter: loop.menuArrayRoom_idx == 0
                                for: menuButtonRoom
                                fragment: true
                                in: =loop.menuArrayRoom
                                map: ((loop.menuButtonRoom.metadata && loop.menuButtonRoom.metadata.widgetOrder && loop.menuButtonRoom.metadata.widgetOrder.value) || 0).toString().padStart(3,'0') + '&' + loop.menuButtonRoom_idx
                              slots:
                                default:
                                  - component: oh-button
                                    config:
                                      action: variable
                                      actionVariable: room
                                      actionVariableValue: =loop.menuArrayRoom[loop.menuButtonRoom_source.sort()[loop.menuButtonRoom_idx].split('&')[1]].name
                                      style:
                                        color: '=vars.room ==(loop.menuArrayRoom[loop.menuButtonRoom_source.sort()[loop.menuButtonRoom_idx].split("&")[1]].name) ? textColor : "#8C8C8C"'
                                        flex: 0 0 auto
                                        height: 2em
                                        order: =(((vars.buttonIndexRoom || 0) % loop.menuButtonRoom_source.length) + loop.menuButtonRoom_source.length + loop.menuButtonRoom_idx) % loop.menuButtonRoom_source.length
                                        text-decoration: underline
                                        text-decoration-color: '=vars.room ==(loop.menuArrayRoom[loop.menuButtonRoom_source.sort()[loop.menuButtonRoom_idx].split("&")[1]].name) ? "#F8BB00" : "transparent"'
                                        text-underline-offset: 4px
                                      text: =loop.menuArrayRoom[loop.menuButtonRoom_source.sort()[loop.menuButtonRoom_idx].split('&')[1]].label
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: buttonIndexRoom
                    actionVariableValue: =(vars.buttonIndexRoom || 0) + 1
                    iconF7: chevron_right
                    style:
                      color: "#F8BB00"
                      flex: 0 0 auto
                      height: 2em
    - component: f7-block
      config:
        style:
          flex: 1 1 auto
          margin-bottom: -1em
          margin-top: -1em
          overflow: scroll
      slots:
        default:
          - component: widget:main_widget_Weather_Card
            config:
              bigCard: true
              dateFormat: true
              itemPrefix: OneCallAPIweatherandforecast_
              locationTitle: =props.locationTitle
              sunIndicator: true
              visible: '=(!vars.objVar || ((vars.objVar.selectSection=="SECTION0") && !vars.objVar.selectThing)) ? true : false'
          - component: oh-repeater
            config:
              fetchMetadata: semantics,metadata,listWidget
              for: sceneItem
              groupItem: =props.scenesGroup
              sourceType: itemsInGroup
            slots:
              default:
                - component: widget:main_widget_Scene_Card
                  config:
                    scene: =loop.sceneItem.name
                    sceneName: =loop.sceneItem.label
                    visible: '=vars.objVar ? ((vars.objVar.selectSection + vars.objVar.selectThing)=="SECTION0Scenes") ? true : false : false'
          - component: oh-repeater
            config:
              fetchMetadata: semantics,metadata,listWidget
              filter: loop.equipmentItem.metadata.semantics.config.hasLocation == vars.room
              for: equipmentItem
              itemTags: Blinds
              sourceType: itemsWithTags
            slots:
              default:
                - component: oh-repeater
                  config:
                    fetchMetadata: semantics,metadata,listWidget
                    filter: '(loop.shutterItem.type=="Rollershutter") ? true : false'
                    for: shutterItem
                    groupItem: =loop.equipmentItem.name
                    sourceType: itemsInGroup
                  slots:
                    default:
                      - component: widget:main_widget_Rollershutter_Card
                        config:
                          RollerItem: =loop.shutterItem.name
                          visible: '=vars.objVar.selectThing=="Rollers" ? true : false'
          - component: oh-repeater
            config:
              fetchMetadata: semantics,metadata,listWidget
              filter: loop.equipmentItem.metadata.semantics.config.hasLocation == vars.room
              for: equipmentItem
              itemTags: Lightbulb
              sourceType: itemsWithTags
            slots:
              default:
                - component: widget:main_widget_Light_Card
                  config:
                    equipmentItem: =loop.equipmentItem.name
                    visible: '=vars.objVar.selectThing=="Lights" ? true : false'
          - component: oh-repeater
            config:
              fetchMetadata: semantics,metadata,listWidget
              filter: loop.equipmentItem.metadata.semantics.config.hasLocation == vars.room
              for: equipmentItem
              itemTags: RadiatorControl
              sourceType: itemsWithTags
            slots:
              default:
                - component: oh-repeater
                  config:
                    fetchMetadata: semantics,metadata,listWidget
                    for: tempItem
                    groupItem: =loop.equipmentItem.name
                    sourceType: itemsInGroup
                  slots:
                    default:
                      - component: widget:Temp_Control
                        config:
                          style:
                            flex: 1 1 auto
                            overflow-y: auto
                            position: relative
                          visible: '=vars.objVar.selectThing=="Climate" ? true : false'
                          widgettrend: =loop.tempItem.name
          - component: widget:main_widget_Security_Card
            config:
              securityGroup: =props.securityGroup
              securityMode: =props.securityMode
              visible: '=vars.objVar ? ((vars.objVar.selectSection + vars.objVar.selectThing)=="SECTION0Security") ? true : false : false'
          - component: Label
            config:
              style:
                flex: 1 1 auto
                overflow-y: auto
                position: relative
              text: =vars.objVar.selectSection + vars.floor
              visible: "=vars.objVar ? true : false"
    - component: f7-block
      config:
        style:
          flex: 0 0 auto
          margin-bottom: -2em
          overflow: scroll
        visible: '=vars.objVar ? (vars.objVar.selectSection=="SECTION0") ? true : false : false'
      slots:
        default:
          - component: f7-segmented
            config:
              class:
                - segmented-strong
              style:
                --f7-segmented-strong-between-buttons: 0px
                --f7-segmented-strong-bg-color: transparent
                --f7-segmented-strong-button-font-weight: 300
                --f7-segmented-strong-button-hover-bg-color: rgba(255, 255, 255, 0.15)
                --f7-segmented-strong-padding: 0px
            slots:
              default:
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: objVar
                    actionVariableValue:
                      selectSection: =vars.objVar.selectSection
                      selectThing: Security
                    class:
                      - padding-top-half
                      - display-flex
                      - flex-direction-column
                    fill: '=vars.objVar.selectThing=="Security" ? true : false'
                    icon-f7: shield_fill
                    iconColor: green
                    iconSize: 20
                    style:
                      --f7-button-bg-color: '=vars.objVar.selectThing=="Security" ? "#F8BB00" : "transparent"'
                      --f7-button-border-radius: 15px
                      --f7-button-hover-bg-color: '=vars.objVar.selectThing=="Security" ? "F8BB00" : "transparent"'
                      --f7-button-padding-horizontal: 0px
                      --f7-button-padding-vertical: 0px
                      --f7-button-text-color: '=vars.objVar.selectThing=="Security" ? "#6A6A6A" : "#8C8C8C"'
                      font-size: 12px
                      height: auto
                    text: Security
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: objVar
                    actionVariableValue:
                      selectSection: =vars.objVar.selectSection
                      selectThing: Scenes
                    class:
                      - padding-top-half
                      - display-flex
                      - flex-direction-column
                    fill: '=vars.objVar.selectThing=="Scenes" ? true : false'
                    icon-f7: rectangle_on_rectangle_angled
                    iconColor: textColor
                    iconSize: 20
                    style:
                      --f7-button-bg-color: '=vars.objVar.selectThing=="Scenes" ? "#F8BB00" : "transparent"'
                      --f7-button-border-radius: 15px
                      --f7-button-hover-bg-color: '=vars.objVar.selectThing=="Scenes" ? "F8BB00" : "transparent"'
                      --f7-button-padding-horizontal: 0px
                      --f7-button-padding-vertical: 0px
                      --f7-button-text-color: '=vars.objVar.selectThing=="Scenes" ? "#6A6A6A" : "#8C8C8C"'
                      font-size: 12px
                      height: auto
                    text: Scenes
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: objVar
                    actionVariableValue:
                      selectSection: =vars.objVar.selectSection
                      selectThing: Weather
                    class:
                      - padding-top-half
                      - display-flex
                      - flex-direction-column
                    fill: '=vars.objVar.selectThing=="Weather" ? true : false'
                    icon-f7: cloud
                    iconColor: textColor
                    iconSize: 20
                    style:
                      --f7-button-bg-color: '=vars.objVar.selectThing=="Weather" ? "#F8BB00" : "transparent"'
                      --f7-button-border-radius: 15px
                      --f7-button-hover-bg-color: '=vars.objVar.selectThing=="Weather" ? "F8BB00" : "transparent"'
                      --f7-button-padding-horizontal: 0px
                      --f7-button-padding-vertical: 0px
                      --f7-button-text-color: '=vars.objVar.selectThing=="Weather" ? "#6A6A6A" : "#8C8C8C"'
                      font-size: 12px
                      height: auto
                    text: Weather
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: objVar
                    actionVariableValue:
                      selectSection: =vars.objVar.selectSection
                      selectThing: HVAC
                    class:
                      - padding-top-half
                      - display-flex
                      - flex-direction-column
                    fill: '=vars.objVar.selectThing=="HVAC" ? true : false'
                    icon-f7: flame
                    iconColor: textColor
                    iconSize: 20
                    style:
                      --f7-button-bg-color: '=vars.objVar.selectThing=="HVAC" ? "#F8BB00" : "transparent"'
                      --f7-button-border-radius: 15px
                      --f7-button-hover-bg-color: '=vars.objVar.selectThing=="HVAC" ? "F8BB00" : "transparent"'
                      --f7-button-padding-horizontal: 0px
                      --f7-button-padding-vertical: 0px
                      --f7-button-text-color: '=vars.objVar.selectThing=="HVAC" ? "#6A6A6A" : "#8C8C8C"'
                      font-size: 12px
                      height: auto
                    text: HVAC
    - component: f7-block
      config:
        style:
          background: =props.bnavColor
          border-radius: 0px 0px 10px 10px
          flex: 0 0 auto
          margin-bottom: -2em
          overflow: scroll
        visible: '=vars.objVar ? (vars.objVar.selectSection=="SECTION0") ? false : true : false'
      slots:
        default:
          - component: f7-segmented
            config:
              class:
                - segmented-strong
              style:
                --f7-segmented-strong-between-buttons: 0px
                --f7-segmented-strong-bg-color: transparent
                --f7-segmented-strong-button-font-weight: 300
                --f7-segmented-strong-button-hover-bg-color: rgba(255, 255, 255, 0.15)
                --f7-segmented-strong-padding: 0px
            slots:
              default:
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: objVar
                    actionVariableValue:
                      selectSection: =vars.objVar.selectSection
                      selectThing: Lights
                    class:
                      - padding-top-half
                      - display-flex
                      - flex-direction-column
                    fill: '=vars.objVar.selectThing=="Lights" ? true : false'
                    icon-f7: lightbulb
                    iconColor: '=vars.objVar.selectThing=="Lights" ? "black" : "white"'
                    iconSize: 20
                    style:
                      --f7-button-bg-color: transparent
                      --f7-button-border-radius: 15px
                      --f7-button-hover-bg-color: '=vars.objVar.selectThing=="Lights" ? "F8BB00" : "transparent"'
                      --f7-button-padding-horizontal: 0px
                      --f7-button-padding-vertical: 0px
                      --f7-button-text-color: '=vars.objVar.selectThing=="Lights" ? "black" : "white"'
                      font-size: 12px
                      height: auto
                    text: Lights
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: objVar
                    actionVariableValue:
                      selectSection: =vars.objVar.selectSection
                      selectThing: Climate
                    class:
                      - padding-top-half
                      - display-flex
                      - flex-direction-column
                    fill: '=vars.objVar.selectThing=="Climate" ? true : false'
                    icon-f7: snow
                    iconColor: '=vars.objVar.selectThing=="Climate" ? "black" : "white"'
                    iconSize: 20
                    style:
                      --f7-button-bg-color: transparent
                      --f7-button-border-radius: 15px
                      --f7-button-hover-bg-color: '=vars.objVar.selectThing=="Climate" ? "F8BB00" : "transparent"'
                      --f7-button-padding-horizontal: 0px
                      --f7-button-padding-vertical: 0px
                      --f7-button-text-color: '=vars.objVar.selectThing=="Climate" ? "black" : "white"'
                      font-size: 12px
                      height: auto
                    text: Climate
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: objVar
                    actionVariableValue:
                      selectSection: =vars.objVar.selectSection
                      selectThing: Rollers
                    class:
                      - padding-top-half
                      - display-flex
                      - flex-direction-column
                    fill: '=vars.objVar.selectThing=="Rollers" ? true : false'
                    icon-f7: archivebox
                    iconColor: '=vars.objVar.selectThing=="Rollers" ? "black" : "white"'
                    iconSize: 20
                    style:
                      --f7-button-bg-color: transparent
                      --f7-button-border-radius: 15px
                      --f7-button-hover-bg-color: '=vars.objVar.selectThing=="Rollers" ? "F8BB00" : "transparent"'
                      --f7-button-padding-horizontal: 0px
                      --f7-button-padding-vertical: 0px
                      --f7-button-text-color: '=vars.objVar.selectThing=="Rollers" ? "black" : "white"'
                      font-size: 12px
                      height: auto
                    text: Rollers
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: objVar
                    actionVariableValue:
                      selectSection: =vars.objVar.selectSection
                      selectThing: Energy
                    class:
                      - padding-top-half
                      - display-flex
                      - flex-direction-column
                    fill: '=vars.objVar.selectThing=="Energy" ? true : false'
                    icon-f7: bolt
                    iconColor: '=vars.objVar.selectThing=="Energy" ? "black" : "white"'
                    iconSize: 20
                    style:
                      --f7-button-bg-color: transparent
                      --f7-button-border-radius: 15px
                      --f7-button-hover-bg-color: '=vars.objVar.selectThing=="Energy" ? "F8BB00" : "transparent"'
                      --f7-button-padding-horizontal: 0px
                      --f7-button-padding-vertical: 0px
                      --f7-button-text-color: '=vars.objVar.selectThing=="Energy" ? "black" : "white"'
                      font-size: 12px
                      height: auto
                    text: Energy


looks good for me with one addition/question: Why not use an “All Room” for Rooms menu like for the Floors menu?

Cause I voted against „all“ option on both, floor and room. :wink:
That would be really complex, error prone and perhaps a really long list of information to show.

1 Like

Approved with the exception of implementing „All“ menu entries.

1 Like

it’s also fine for me. Let’s do it without “all” for both sections and if someone wants to add it in future he’s free to so.

I think we have to cut out a bit of complexity and therefore you are absolutely right with your vote!

1 Like

This is what hmerk was referring to when he said that it has to do with whether vars.objVar exists. Right now, before you press any button, vars.ObjVar equals undefined, so there’s no way that vars.objVar.selectSection can equal "SECTION" + loop.baseMenu_idx. If you want the expression to be responsive before you press a button then you have to account for the undefined state of vars.objVar.

Usually this is most easily done with a simple OR statement because undefined will be interpreted as a false value. Because we’re looking at the property of an object it’s usually best to test each level as we go. So if you have:

((var.objVar && vars.objVar.selectSection) || "Section0")

first the parser will look at var.objVar if that doesn’t exist, then already the innner AND statement is false and the parser moves to the second part of the outer OR statement. "Section0" is a non-zero non-false value (therefore it counts as true) so the OR statement returns that value. The same line of reasoning applies if vars.objVar does exist but vars.objVar.selectSection does not. However, if vars.objVar does exist and vars.objVar.selectSection also exists then the inner AND statement is true and the most recently evaluated value (in this case vars.objVar.selectSection) is returned.

1 Like

Ok, so i will try to bring all the latest changes/improvements together tonight and start with the information for the floors menu.

I understand what you mean and what you say - but not how to do it :frowning:

I use this code:

                          class: '=((vars.objVar.selectSection=="SECTION" + loop.baseMenu_idx) || "Section0") ? "selected_menu_item" : "unselected_menu_item"'

this should set it to “Section0” or am I wrong? Or do I use it completely wrong (did not understand how to check objvar)… Is class at all the right place for this?

Hey @hmerk cause of all the progress I totally forgot this issue.

I created a non semantic group and assigned in a first step a light.

The non-semantic group is shown in the rooms but the lights does not appear. My config is:

Seems I missed something for the light - but what?

class is the correct place, you are making a jump in reasoning that most computer languages don’t/can’t. While there are some cases where it is OK for a value to be undefined or whatever the language equivalent is, trying to then do something more with that value is an immediate issue because it is “undefined” so the language has no context to work with. If I ask you what a “procklenard” is, you would say “there’s no such thing” which is fine answer. If I ask you “what do you get when you double a procklenard” your only possible answer is “I can’t even begin to tell you, because I don’t know what a procklenard is”.

If vars.objVar doesn’t exist, the parser is happy to tell you that. But if you ask it what is the selectSection property of something that doesn’t exist, it’s only possible answer is, “I can’t even begin to tell you, because I don’t know what vars.objVar is”. In computer speak, “I can’t even begin to tell you…” is just error.

This is what I meant by this line. If there’s ever a chance that an expression with vars.objVar is going to be needed before vars.objVar exists (which of course there is), then we can’t try to use that value for anything else (getting a property or it, or adding it to something else, for example) until we give the expression parser a way to fall-back to a sensible value. That’s what those && and || statements do.

The other piece to this that I didn’t explicitly describe is that the && and || statements do not just return true or false they return whatever the most recent value they evaluated is as soon as they know whether the logic is true or false. For example (2 == 3 || "orange") first checks 2 == 3, well, this is obviously false, but since the OR statement could still be true it has to check the second value. So it then evaluates "orange". Well, that is a value that exists, is not 0 and is not false so as far as the parser is concerned that is true and the OR statement returns the last thing it evaluated: "orange".

So you want a statement that returns vars.objVar.selectSection, but only if vars.objVar and vars.objVar.selectSection exist. One way to do that would be:

(vars.objVar && vars.objVar.selectSection)

but then you want the expression to return "Section0" if any of that up above equals false:

((vars.objVar && vars.objVar.selectSection) || "Section0")

now you’re ready to test if the result of that actually equals “Section” plus whichever button you are on:

((vars.objVar && vars.objVar.selectSection) || "Section0") == "Section"  + loop.baseMenu_idx

Finally you can use that test as the condition for the ternary statement that decides which class to give your button:

class: '=(((vars.objVar && vars.objVar.selectSection) || "Section0") == "Section"  + loop.baseMenu_idx) ? "selected_menu_item" : "unselected_menu_item"'