Building Pages in the OH3 UI: documentation draft (2/3)

Hello Reiner,

I have tried to copy your code into the “create Widget” section.
It looks like some stupid mistake, but I have no idea how to run your code.
-> Could you share the complete code?

I try to create a simple Widget like this:
image

Hey @SmartHome4all

you need a root component, which all of the other components will sit in. Normaly you would use something like f7-card, f7-block or f7-page here.
Notice that you dont need to write the leading - on the root component.

So it would look like:

component: f7-card
config:
  title: Test
slots:
  default:
    - component: f7-button
    ...
1 Like

I successfully created a transparent f7-card that turns white once the item is “on”. I am struggling to understand to make the whole card clickable, my current workaround is a transparent button at the bottom. Can someone point me in the right direction how to make the f7-card ?

image
image

yaml:

uid: widget_f7-card_test_v2
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: Feb 3, 2021, 3:13:27 PM
component: f7-card
config:
  style:
    border-radius: var(--f7-card-expandable-border-radius)
    box-shadow: var(--f7-card-expandable-box-shadow)
    background-color: '=(items[props.item].state === "ON") ? "white" : "transparent"'
slots:
  content:
    - component: f7-block
      config:
        style:
          margin: 0px
          padding: 0px
      slots:
        default:
          - component: f7-icon
            config:
              f7: '=(items[props.item].state === "ON") ? "lightbulb_fill" : "lightbulb"'
              size: 24
              margin: 0px
              padding: 0px
              color: '=(items[props.item].state === "ON") ? "yellow" : "black"'
          - component: Label
            config:
              text: =props.prop1
              style:
                font-size: 14px
                font-weight: 500
                margin: 0px
                padding: 0px
                color: '=(items[props.item].state === "ON") ? "black" : "black"'
          - component: Label
            config:
              text: '=(items[props.item].state === "ON") ? "AN" : "AUS"'
              style:
                font-size: 11px
                font-weight: 500
                color: '=(items[props.item].state === "ON") ? "red" : "black"'
          - component: oh-button
            config:
              action: toggle
              actionItem: =props.item
              actionCommand: ON
              actionCommandAlt: OFF
              position: absolute
              width: 250%
              height: 250%
              color: '=(items[props.item].state === "ON") ? "white" : "transparent"'
1 Like

Hey @muelli1967

it seems you were already on the right track - you only missed the style: property in your oh-button.

If you just want to make the card sending a fixed command to an item, it would be enough to overlay the whole card with a oh-link component (you could also use the oh-button component here, if you like the hover effect), like this:

uid: widget_f7-card_test_v2
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: Feb 3, 2021, 3:13:27 PM
component: f7-card
config:
  style:
    border-radius: var(--f7-card-expandable-border-radius)
    box-shadow: var(--f7-card-expandable-box-shadow)
    background-color: '=(items[props.item].state === "ON") ? "white" : "transparent"'
slots:
  content:
    - component: f7-block
      config:
        style:
          margin: 0px
          padding: 0px
      slots:
        default:
          - component: f7-icon
            config:
              f7: '=(items[props.item].state === "ON") ? "lightbulb_fill" : "lightbulb"'
              size: 24
              margin: 0px
              padding: 0px
              color: '=(items[props.item].state === "ON") ? "yellow" : "black"'
          - component: Label
            config:
              text: =props.prop1
              style:
                font-size: 14px
                font-weight: 500
                margin: 0px
                padding: 0px
                color: '=(items[props.item].state === "ON") ? "black" : "black"'
          - component: Label
            config:
              text: '=(items[props.item].state === "ON") ? "AN" : "AUS"'
              style:
                font-size: 11px
                font-weight: 500
                color: '=(items[props.item].state === "ON") ? "red" : "black"'
    - component: oh-link
      config:
        action: toggle
        actionItem: =props.item
        actionCommand: ON
        actionCommandAlt: OFF
        style:
          position: absolute
          width: 100%
          height: 100%
          top: 0
          left: 0

Thanks Rainer for the support. Yep, i missed that oh-link option. Works perfect now!

Just a feedback, i was replacing full tranaparent with a hex code color and a suffix „Hex Opacity Value“ . Here i uses suffix 73 for 45% transparency of the color white „#ffffff73“ when the item is off. Full white for ON.

Looks like this now:

1 Like

I prefer to use RGBA for colours
RGBA (255,255,255,0.1) or (255,255,255,1)

Hi, Popover class got mentioned around post 67, but I’m still struggling with the whole Framework7 to OH3 yaml interfacing.
Any ideas if these can be implemented:

close-by-backdrop-click boolean true When enabled, popover will be closed on backdrop click. By default inherits same app parameter value
close-by-outside-click boolean true When enabled, popover will be closed on when click outside of it. By default inherits same app parameter value
close-on-escape boolean false When enabled, popover sheet will be closed on ESC keyboard key press

Thanks,
Richie

Hey @Richie1972

you have to assign the popover action to a oh-action-component, like oh-link or oh-button and refer its class to the popover component.

To see all available config options in the editor, press CTRL + Space.

    - component: oh-button
      config:
        title: Something
        action: popover
        fill: true
        text: Click me!
        popoverOpen: .popOver
    - component: f7-popover
      config:
        class: popOver
        closeByBackdropClick: true
        closeByOutsideClick: true
        backdrop: false
        closeOnEscape: true
      slots:
        default:
          - component: Label
            config:
              text: Some content!

Hope this helps!

1 Like

Hi,
Thanks for that.
That’s helped me for another issue I was having, but for this one I went with adding a button to the popover:

  • component: oh-button
    config:
    fill: true
    text: X
    class:
    popover-close
    style:
    position: absolute
    top: 4px
    right: 2px

Thanks,
Richie

I solved this for me: I use “items.###.displayState” . I think “displayState” uses the “Pattern” which you can define resp add through Metadata “stateDescription” of the “Item”. There you have to fill in %.2f (which defines 2 decimal numbers)

Is there a way to set a variable too without an action: variable ?

Idea is to evaluate a certain condition only once and use the result multiple times, e.g. for visibility of some of the widget components…

Hey,

I am trying to organize my widgets in a way that they look properly and there are no gaps between rows.

What I have today:

Any idea how to make that disappear? I tried to add two widgets to the same oh-grid-col but then it is not displaying anything.
The code looks like this:

config:
  label: Living Room
  sidebar: true
  order: "1"
blocks:
  - component: oh-block
    config: {}
    slots:
      default:
        - component: oh-grid-row
          config: {}
          slots:
            default:
              - component: oh-grid-col
                config:
                  width: "100"
                  small: "50"
                  medium: "33"
                slots:
                  default:
                    - component: widget:label-cell
                      config:
                        header: Dining Room
                        item: TemperatureDiningRoom_Temperature
                        secondaryitem: TemperatureDiningRoom_Humidity
              - component: oh-grid-col
                config:
                  width: "100"
                  small: "50"
                  medium: "33"
                slots:
                  default:
                    - component: widget:weatherCard
                      config:
                        widget_action: popup
                        widget_actionModal: widget:weatherPopup
                        bigCard: false
                        sunIndicator: true
                        dateScheme: YYYY-DD-MM
                        dateFormat: true
                        itemPrefix2: LocalWeatherAndForecast_
                        itemPrefix: OneCallAPI_
                        widget_actionModalConfig:
                          itemPrefix: OneCallAPI_
                          itemPrefix2: LocalWeatherAndForecast_
                          forecastDays: 4
                        locationTitle: Weather
              - component: oh-grid-col
                config:
                  width: "100"
                  medium: "33"
                slots:
                  default:
                    - component: widget:label-cell
                      config:
                        header: Living Room
                        item: OutletandTemperatureLivingRoom_Temperature
                        secondaryitem: OutletandTemperatureLivingRoom_Humidity
        - component: oh-grid-row
          config: {}
          slots:
            default:
              - component: oh-grid-col
                config:
                  width: "100"
                  small: "50"
                  medium: "33"
                slots:
                  default:
                    - component: widget:Shelly_RGBW
                      config:
                        title: Dining Room RGBW
                        power: RGBWLedStripDiningRoom_Power
                        color: RGBWLedStripDiningRoom_Color
                        gain: RGBWLedStripDiningRoom_Gain
                        white: RGBWLedStripDiningRoom_White
                        colormode: RGBWLedStripDiningRoom_ColorMode
              - component: oh-grid-col
                config:
                  width: "100"
                  small: "50"
                  medium: "33"
                slots:
                  default: []
              - component: oh-grid-col
                config:
                  width: "100"
                  medium: "33"
                slots:
                  default: []
masonry: []

My other question is whether it is possible to have direct links to the UI without the top bar and the left menu bar. I will have some room controller screens based on rPi and I am looking for some kind of kiosk mode.

Thanks!

Hi, your weather widget has a different hight vs. the room temperature widget, so it is a matter of fact that you have gaps. You can consider to use different blocks for it, e.g. a top block with the weather widget and another block for the temperature widgets. then you wont have gaps like this. I have worked around with this and positioned different widget with different sizes in multiple blocks. If you want all of your widgets in the same block, you can alternatively use custom widgets that all have the same hight.

if you then make sure they have the same max width, they flow nicely with the size of the page.

1 Like

trying to answer your second question. You can create a layout page and link directly to it or open it in a browser. I believe you cannot get completely rid of the navigation bar, but minimize it. Here is a good discussion to follow:

Thanks! I’ll come up with something then, either reorg or change the heights.

could you please post the code again I unfortunately can’t set the Hex Opacity Value :frowning: Thank you!!!

i assume you talk about the buttons.

"white" : "rgba(228,228,228,0.9)

ON is white and OFF is rgba value.

Could you please share that weather widget, please? :slight_smile:

Sure. It is based on the weather widget items definition from @RGroll, so using the prefix and items definition:

Here is my code. Please note that i have a link to wetteronline at the bottom of the code. Please adapt or link to whatever you like.

uid: weather_widget_v1
tags:
  - homekit look
  - black
  - in use
props:
  parameters:
    - description: Location?
      label: Location
      name: propLoc
      required: false
      type: TEXT
    - context: item
      description: Outdoor Temperature Item
      label: Item
      name: itemTempOut
      required: false
      type: TEXT
    - context: item
      description: Daily Minimum Temperature
      label: Item
      name: itemTempMin
      required: false
      type: TEXT
    - context: item
      description: Daily Minimum Temperature
      label: Item
      name: itemTempMax
      required: false
      type: TEXT
    - description: <b>Optional prefix</b> for item names.
      label: Item prefix
      name: itemPrefix
      required: false
      type: TEXT
  parameterGroups: []
timestamp: Feb 13, 2021, 12:44:48 PM
component: f7-card
config:
  style:
    noShadow: false
    class:
      - padding
    border-radius: var(--f7-card-expandable-border-radius)
    box-shadow: var(--f7-card-expandable-box-shadow)
    background: linear-gradient(to top, rgba(0,0,0,1) 35%, rgba(80,80,80,1) 100%)
    height: 8.5em
    min-width: 9.5em
    max-width: 400px
slots:
  content:
    - component: f7-block
      config:
        style:
          margin: -9px
          padding: 0px
          display: flex
          flex-direction: column
          align-items: start
    - component: f7-row
      config:
        class:
          - justify-content-left
      slots:
        default:
          - component: Label
            config:
              text: =props.propLoc
              class: -margin-top
              style:
                color: rgb(255,255,255)
                font-size: 20px
                overflow: hidden
                text-overflow: ellipsis
                text-transform: uppercase
                white-space: nowrap
                margin-bottom: 0px
    - component: f7-row
      slots:
        default:
          - component: f7-icon
            config:
              f7: "=(items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '01d') ? 'sun_max_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '01n') ? 'moon_stars_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '02d') ? 'cloud_sun_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '02n') ? 'cloud_moon_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '03d') ? 'cloud_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '03n') ? 'cloud_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '04d') ? 'cloud_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '04n') ? 'cloud_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '09d') ? 'cloud_heavyrain_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '09n') ? 'cloud_heavyrain_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '10d') ? 'cloud_sun_rain_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '10n') ? 'cloud_moon_rain_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '11d') ? 'cloud_sun_bolt_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '11n') ? 'cloud_moon_bolt_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '13d') ? 'cloud_snow_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '13n') ? 'cloud_snow_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '50d') ? 'cloud_fog_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '50n') ? 'cloud_fog_fill' : ''"
              size: 48
              color: white
          - component: Label
            config:
              text: =(Number.parseFloat(items[props.itemTempOut].state.split(" ")[0]) * 100 / 100).toFixed(0) + '°'
              class: -margin-top
              style:
                font-size: 40px
                margin-left: -2px
                margin-top: -9px
                color: rgb(255,255,255)
                white-space: nowrap
                overflow: hidden
                text-overflow: ellipsis
                font-weight: 300
    - component: f7-row
      config:
        class:
          - justify-content-left
      slots:
        default:
          - component: Label
            config:
              text: "=(!props.itemPrefix) ? items.Current_Condition.state : items[props.itemPrefix + 'Current_Condition'].state"
              style:
                font-size: 10px
                margin-left: 1px
                margin-bottom: 0px
                margin-top: 0px
                color: rgb(255,255,255)
                white-space: nowrap
                overflow: hidden
                text-overflow: ellipsis
                font-weight: 400
    - component: f7-row
      config:
        class:
          - justify-content-left
      slots:
        default:
          - component: Label
            config:
              text: ="Hi:" +" " + (Number.parseFloat(items[props.itemTempMax].state.split(" ")[0]) * 100 / 100).toFixed(0) + '°'
              style:
                font-size: 14px
                margin-left: 0px
                margin-top: 0px
                color: rgb(255,255,255)
                white-space: nowrap
                overflow: hidden
                text-overflow: ellipsis
                font-weight: 500
          - component: Label
            config:
              text: ="| Lo:" +" " + (Number.parseFloat(items[props.itemTempMin].state.split(" ")[0]) * 100 / 100).toFixed(0) + '°'
              style:
                font-size: 14px
                margin-left: 0px
                margin-top: 0px
                color: rgb(255,255,255)
                white-space: nowrap
                overflow: hidden
                text-overflow: ellipsis
                font-weight: 400
    - component: oh-link
      config:
        action: url
        actionUrl: http://m.wetteronline.de/yourtown 
        open-in: .popOver
        style:
          position: absolute
          width: 100%
          height: 100%
          top: 0
          left: 0
2 Likes