F7-popover Loss of links with variables

Hello everyone,

I have a problem with a widget I just created.
I have an oh-button that activates an f7-popover that contains oh-links. Each oh-link assigns a different value to the same variable.

This works when there’s a single widget, but not if there’s more than one.
I know I can get around this by creating as many widgets with different variable names, but if anyone has another solution I’m interested.

s

Here is the code for the part concerned:

        - component: f7-col
            slots:
              default:
                - component: oh-button
                  config:
                    class:
                      - display-flex
                      - justify-content-center
                    action: popover
                    popoverOpen: .detailList
                    style:
                      color: white
                      height: 100px
                  slots:
                    default:
                      - component: oh-icon
                        config:
                          height: 100px
                          icon: "=(items[props.mode_chauffage].state === '1') ? 'iconify:tabler:power' : (items[props.mode_chauffage].state === '2') ? 'iconify:heroicons:moon' : (items[props.mode_chauffage].state === '3') ? 'iconify:tabler:sun-filled' : (items[props.mode_chauffage].state === '4') ? 'iconify:icon-park-outline:sleep-one': (items[props.mode_chauffage].state === '5') ? 'iconify:iconoir:snow-flake' : 'Not Set'"
                          class:
                            - padding
                      - component: f7-popover
                        config:
                          class: detailList
                          closeByBackdropClick: true
                          closeByOutsideClick: true
                          backdrop: false
                          closeOnEscape: true
                          style:
                            --f7-popover-width: 250px
                            --f7-popover-border-radius: 4px
                        slots:
                          default:
                            - component: oh-link
                              config:
                                action: command
                                actionCommand: ='3'
                                actionItem: =props.mode_chauffage
                                popoverClose: .detailList
                              slots:
                                default:
                                  - component: oh-icon
                                    config:
                                      icon: iconify:tabler:sun-filled
                                      width: 50
                            - component: oh-link
                              config:
                                action: command
                                actionCommand: ='2'
                                actionItem: =props.mode_chauffage
                                popoverClose: .detailList
                              slots:
                                default:
                                  - component: oh-icon
                                    config:
                                      icon: iconify:heroicons:moon
                                      width: 50
                            - component: oh-link
                              config:
                                action: command
                                actionCommand: ='4'
                                actionItem: =props.mode_chauffage
                                popoverClose: .detailList
                              slots:
                                default:
                                  - component: oh-icon
                                    config:
                                      icon: iconify:icon-park-outline:sleep-one
                                      width: 50
                            - component: oh-link
                              config:
                                action: command
                                actionCommand: ='5'
                                actionItem: =props.mode_chauffage
                                popoverClose: .detailList
                              slots:
                                default:
                                  - component: oh-icon
                                    config:
                                      icon: iconify:iconoir:snow-flake
                                      width: 50
                            - component: oh-link
                              config:
                                action: command
                                actionCommand: ='1'
                                actionItem: =props.mode_chauffage
                                popoverClose: .detailList
                              slots:
                                default:
                                  - component: oh-icon
                                    config:
                                      icon: iconify:tabler:power
                                      width: 50

This is a funny quirk of how the f7 modals work. Even though you build this popover in three different widgets, because you give it the same class in each three, the f7 library overwrites each popover with the next one. This means that really each of your widgets is opening the popover for the third widget because that was the last popover created (which explains why it is only the value in the third widget that is changing no matter which widget opens the popover).

There are two essential solutions to this. One is easy but winds up with multiple (possibly resource intensive) popovers, the other is a little more involved, and utilizes the single popover but makes it dynamic enough to link to the widget that opened it.

First solution: Just give each of your widget popovers a different class. Add a property to your base widget that is a string which allows you to set an extra identifier for your popover (or just use the mode_chauffage property that is already unique to each widget). Then on the popover class itself, the links that open the popover, and the links that close the popover use: detailList + identifier instead of just detailList. For example, if you define a new popoverId property:

- component: f7-popover
  config:
    class: ='detailList' + props.popoverId

Then each time you add the widget to a page and configure the widget make sure to add a unique ID in that property.

Second solution: if you use a variable instead of a property, that variable can be shared between the widgets on a page (and the modal elements they open). So, the button that opens the popover would use the variable action (popoverOpen is an f7 property and is independent of OH so you don’t need to set the button’s action to popover, it can be something else, which is useful here), and set that variable to the value of the item name that widget controls:

- component: oh-button
  config:
    class:
      - display-flex
      - justify-content-center
    action: variable
    actionVariable: popoverItem
    actionVariableValue: =props.mode_chauffage
    popoverOpen: .detailList

The you would change the popover links to use that variable instead of the property. Lastly you would want to add the variable to the page definition as well to make sure that the variables scope is the whole page which means that each widget is sharing the same variable.

2 Likes

Hello Justin and thank you for your message.

I’ve tried to apply your instructions for the 2nd solution and I think I’m making beginner’s mistakes.
I’m not sure about the oh-link modification: (actionItem: =vars.popoverItem)

                            - component: oh-link
                              config:
                                action: command
                                actionCommand: ='3'
                                actionItem: =vars.popoverItem
                                popoverClose: .detailList
                              slots:
                                default:
                                  - component: oh-icon
                                    config:
                                      icon: iconify:tabler:sun-filled
                                      width: 50

By doing this, only the last widget added works. If this last widget is manipulated, then the first two widgets “work” but modify only the last widget.

also, I haven’t yet declared the variable in the page containing the 3 widgets, would this do?

components:
  - id: popoverItem
    value: ""

What you’ve posted should work depending on the value of vars.popoverItem. Without seeing the whole code as it stands at the moment I can’t say exactly what’s wrong, but it sounds like popoverItem is not being properly set in the other widgets.

No, to define variables for a page, you have to add the defineVars parameter to the config of the page itself.

config:
  defineVars:
    popoverItem: ''

No worries, here’s the complete widget code

uid: SamTemperatureControl
tags:
  - card
props:
  parameters:
    - context: item
      label: Température extérieure
      name: temperatureext
      required: false
      type: TEXT
    - context: item
      label: Ajustement Température
      name: choixtemperature
      required: false
      type: TEXT
    - context: item
      label: Chauffage actif
      name: chauffage_active
      required: false
      type: TEXT
    - context: item
      label: Mode Chauffage
      name: mode_chauffage
      required: false
      type: TEXT
    - context: item
      label: Température de la pièce
      name: temperature
      required: false
      type: TEXT
    - context: item
      label: Humidité de la pièce
      name: humidite
      required: false
      type: TEXT
    - label: Nom de la pièce
      name: piece
      required: false
      type: TEXT
  parameterGroups: []
timestamp: Dec 9, 2023, 3:44:20 PM
component: f7-card
config:
  title: =props.title
slots:
  default:
    - component: f7-row
      slots:
        default:
          - component: f7-col
            config:
              class:
                - display-flex
                - justify-content-center
            slots:
              default:
                - component: oh-icon
                  config:
                    color: white
                    icon: iconify:mdi:home-temperature-outline
                    width: 24
                - component: Label
                  config:
                    text: =items[props.temperatureext].state
                    style:
                      fontSize: 15px
          - component: f7-col
            slots:
              default:
                - component: oh-button
                  config:
                    class:
                      - display-flex
                      - justify-content-center
                    action: variable
                    actionVariable: popoverItem
                    actionVariableValue: =props.mode_chauffage
                    popoverOpen: .detailList
                    style:
                      color: white
                      height: 100px
                  slots:
                    default:
                      - component: oh-icon
                        config:
                          height: 100px
                          icon: "=(items[props.mode_chauffage].state === '1') ? 'iconify:tabler:power' : (items[props.mode_chauffage].state === '2') ? 'iconify:heroicons:moon' : (items[props.mode_chauffage].state === '3') ? 'iconify:tabler:sun-filled' : (items[props.mode_chauffage].state === '4') ? 'iconify:icon-park-outline:sleep-one': (items[props.mode_chauffage].state === '5') ? 'iconify:iconoir:snow-flake' : 'Not Set'"
                          class:
                            - padding
                      - component: f7-popover
                        config:
                          class: detailList
                          closeByBackdropClick: true
                          closeByOutsideClick: true
                          backdrop: false
                          closeOnEscape: true
                          style:
                            --f7-popover-width: 250px
                            --f7-popover-border-radius: 4px
                        slots:
                          default:
                            - component: oh-link
                              config:
                                action: command
                                actionCommand: ='3'
                                actionItem: =vars.popoverItem
                                popoverClose: .detailList
                              slots:
                                default:
                                  - component: oh-icon
                                    config:
                                      icon: iconify:tabler:sun-filled
                                      width: 50
                            - component: oh-link
                              config:
                                action: command
                                actionCommand: ='2'
                                actionItem: =vars.popoverItem
                                popoverClose: .detailList
                              slots:
                                default:
                                  - component: oh-icon
                                    config:
                                      icon: iconify:heroicons:moon
                                      width: 50
                            - component: oh-link
                              config:
                                action: command
                                actionCommand: ='4'
                                actionItem: =vars.popoverItem
                                popoverClose: .detailList
                              slots:
                                default:
                                  - component: oh-icon
                                    config:
                                      icon: iconify:icon-park-outline:sleep-one
                                      width: 50
                            - component: oh-link
                              config:
                                action: command
                                actionCommand: ='5'
                                actionItem: =vars.popoverItem
                                popoverClose: .detailList
                              slots:
                                default:
                                  - component: oh-icon
                                    config:
                                      icon: iconify:iconoir:snow-flake
                                      width: 50
                            - component: oh-link
                              config:
                                action: command
                                actionCommand: ='1'
                                actionItem: =vars.popoverItem
                                popoverClose: .detailList
                              slots:
                                default:
                                  - component: oh-icon
                                    config:
                                      icon: iconify:tabler:power
                                      width: 50
          - component: f7-col
            config:
              class:
                - display-flex
                - justify-content-center
            slots:
              default:
                - component: oh-icon
                  config:
                    color: white
                    icon: "=(items[props.chauffage_active].state === 'ON') ? 'iconify:material-symbols:heat' : ''"
                    width: 22
    - component: f7-row
      slots:
        default:
          - component: f7-col
            config:
              class:
                - display-flex
                - justify-content-center
            slots:
              default:
                - component: oh-icon
                  config:
                    color: white
                    icon: iconify:mdi:temperature
                    width: 21
                - component: Label
                  config:
                    text: =items[props.temperature].state+" °C"
                    style:
                      fontSize: 15px
                - component: oh-icon
                  config:
                    color: white
                    icon: iconify:mdi:water
                    width: 23
                - component: Label
                  config:
                    text: =items[props.humidite].state+" %"
                    style:
                      fontSize: 15px
                      top: 0px
    - component: f7-row
      slots:
        default:
          - component: oh-button
            config:
              action: command
              actionCommand: =Math.max(0, Number(items[props.choixtemperature].state)-0.5).toFixed(1).toString()
              actionItem: =props.choixtemperature
              color: white
              iconF7: minus_circle
              iconSize: 30
              style:
                top: 25px
          - component: Label
            config:
              text: =items[props.choixtemperature].state+" °C"
              style:
                fontSize: 50px
          - component: oh-button
            config:
              action: command
              actionCommand: =Math.min(30, Number(items[props.choixtemperature].state)+0.5).toFixed(1).toString()
              actionItem: =props.choixtemperature
              color: white
              iconF7: plus_circle
              iconSize: 30
              style:
                top: 25px
          - component: f7-col
            config:
              class:
                - display-flex
                - justify-content-center
            slots:
              default:
                - component: Label
                  config:
                    text: =props.piece
                    style:
                      fontSize: 30px

and thanks for telling me how to add the defineVars parameter to the config of the page.

I stand corrected. You properly modified your configuration, but the popovers are not updating the way they should in response to variable changes. Even attempting to force an update doesn’t seem to be working. I wonder if this is another side-effect of the new caching that hasn’t been reported yet?

I’m going to have to dig into this a little more deeply to see where the error is.

In the meantime, I am 100% confident that the first method I mentioned (unique IDs for the popover classes) will work.

Good evening Justin,

Solution 1 is functional, thank you very much for that.
FYI my version of OH is 3.4.3, if that can influence the result for solution 2.

I want to tell you how impressed I am by the number of people you help, because I see your name in most of my searches!
:wink: