Building Pages in OH 3 - Custom User Defined Widgets

Those are really good points! May I suggest adding the search quick link into the tutorial?
If I’m not mistaken this should be the correct combination of tags and category:
https://community.openhab.org/search?q=tag:openhab3,widget%20%20%23add-ons:uis

Thanks again, both for the tutorials as well as the Q&A!

Unfortunately, the widget builder does not have a form to easily create a widget. So I recommend opening another tab and creating the widget the way described in the previous page of this tutorial. Make sure to select the card type instead of accepting the default and to select the Item so that all the fields are present in the code tab.

Hi Rich Im having a go at this and hitting some beginners problems - I don’t understand this part above - what is the previous page.

I tried just adding a new widget by clicking on the + sign in the widget builder and copying in the code from your example. I added the widget as the default widget to a light item then try to add this to a page it does not work. I select the item but it does not keep the selection. Do I need to add this to a page in a specific way - through a list item etc…It seems to be working in the prebuilt Home pages but I was assuming these widgets can be used in the page builder ui?

previous page of the tutorial that discussed item customization.

The example here only works as a list widget. It has to be an element in a list and won’t render by itself. You can’t just put it on a page.

You have to create a standalone widget for that. They use different building blocks.

Hey rlkoshak, I never worked on a wiki entry, but I read your initial statement as an invitation to just try to improve.
So I had initial struggles understanding the props purpose and have rewritten this believing my version is easier to understand.
Here is old followed by new:

Hi @rlkoshak
I am currently trying to create a widget and are struggling a little bit.
I want to create one “element” for a tv channel with the current show and the upcoming show. When I click anywhere in the “element” then an Item should receive the value of the channel.
I am not able to create the element to be like “one”. Instead I needed 4 oh-label-cards within a row. But then There is a lot of space where nothing will happen when I click on it.

image

Is it possible to create a widget where I can click anywhere in the element and then a command will be sent?

My current widget looks as follows:

uid: Fernsehprogramm
tags: []
props:
  parameters:
    - description: Title for the widget
      label: Static Title
      name: title
      required: false
      type: TEXT
    - context: item
      label: Select a 'Fernsehprogramm Group Item'
      name: prefix
      required: true
      type: TEXT
  parameterGroups: []
timestamp: Apr 10, 2021, 1:58:19 AM
component: f7-card
config:
  title: =items[props.prefix+"_Sender"].state
  action: command
  actionItem: Fernsehsender
  actionCommand: =items[props.prefix+"_Sender"].state
slots:
  default:
    - component: f7-row
      config:
        title: =items[props.prefix+"_Sender"].state
        action: command
        actionItem: Fernsehsender
        actionCommand: =items[props.prefix+"_Sender"].state
        class:
          - justify-content-center
      slots:
        default:
          - component: oh-label-card
            config:
              action: command
              actionItem: Fernsehsender
              actionCommand: =items[props.prefix+"_Sender"].state
              label: =items[props.prefix+"_Start"].displayState
              fontSize: 14px
    - component: f7-row
      config:
        class:
          - justify-content-center
      slots:
        default:
          - component: oh-label-card
            config:
              action: command
              actionItem: Fernsehsender
              actionCommand: =items[props.prefix+"_Sender"].state
              label: =items[props.prefix+"_Titel"].state
              fontSize: 14px
    - component: f7-row
      config:
        class:
          - justify-content-center
      slots:
        default:
          - component: oh-label-card
            config:
              action: command
              actionItem: Fernsehsender
              actionCommand: =items[props.prefix+"_Sender"].state
              label: =items[props.prefix+"_Start_Next"].displayState
              fontSize: 14px
    - component: f7-row
      config:
        class:
          - justify-content-center
      slots:
        default:
          - component: oh-label-card
            config:
              action: command
              actionItem: Fernsehsender
              actionCommand: =items[props.prefix+"_Sender"].state
              label: =items[props.prefix+"_Titel_Next"].state
              fontSize: 14px

I am not an expert in this stuff but I imagine if you put them all into an oh-card then you should be able to apply an action to the whole card instead of just one element. But beyond the basics I’m not an expert.

@rlkoshak
Is oh-card the right card? For me it doesn’t look like this is working. I can’t also find a documentation:

As I said, I’m not expert. But you need something basic to contain everything. Maybe an f7-card will do.

So maybe do you know how to create a “line break” within one label item? So I could use just one label with multiple lines of text in it instead of creating a widget with multiple lable items

Frankly, if it’s not already posted above or in one of my tutorials or it’s not in the docs I don’t know it. Seriously, all I’ve done are the merest basics with custom widgets. I’ve done nothing fancy and what little bit I’ve done outside of the very simple took help from others.

I believe if you put all your content in the default slot of an oh-link and set the link action to send the command of interest then the action behavior of the link will trigger no matter where in the content you click (note: if you have an item with its own action in the link content, clicking on that will trigger BOTH actions)

For example the following code

uid: widget_link_demo
component: f7-card
config: {}
slots:
  default:
    - component: oh-link
      config:
        action: options
        actionItem: Item_With_Command_Options
      slots:
        default:
          - component: f7-card
            slots:
              default:
              - component: oh-button
                config:
                  text: Button 1
                  raised: true
                  action: toggle
                  actionItem: Toggle_Switch_Item
                  actionCommand: ON
                  actionCommandAlt: OFF
              - component: f7-icon
                config:
                  f7: airplane
              - component: oh-button
                config:
                  text: Button 2
                  raised: true

Produces this little area:
image

Clicking on any part of that (either button or the airplane) with trigger the series of options buttons from Item_With_Command_Options, however, if that click is on the Button 1 part of the area then the options will AND the switch will get toggled.

1 Like

Unfortunately it is not working.


I have it in the oh-link but nothing is like a link.

uid: Fernsehprogramm
tags: []
props:
  parameters:
    - description: Title for the widget
      label: Static Title
      name: title
      required: false
      type: TEXT
    - context: item
      label: Select a 'Fernsehprogramm Group Item'
      name: prefix
      required: true
      type: TEXT
  parameterGroups: []
timestamp: Apr 13, 2021, 9:05:22 PM
component: f7-card
config:
  title: =items[props.prefix+"_Sender"].state
  action: command
  actionItem: Fernsehsender
  actionCommand: =items[props.prefix+"_Sender"].state
slots:
  default:
  
  
    - component: oh-link
      config:
        action: command
        actionItem: Fernsehsender
        actionCommand: =items[props.prefix+"_Sender"].state
      slots:
        default:
        
    - component: f7-row
      slots:
        default:

          - component: Label
            config:
              text: =items[props.prefix+"_Start"].displayState              
              style:
                color: rgba(0,200,0,.7)
          - component: Label
            config:
              text: =items[props.prefix+"_Titel"].state
    - component: f7-row
      slots:
        default:
          - component: Label
            config:
              style:
                color: rgba(200,155,0,.7)
              text: =items[props.prefix+"_Start_Next"].displayState
          - component: Label
            config:
              text: =items[props.prefix+"_Titel_Next"].state


Your indentation is wrong. Your oh-link and the following f7-row are on the same level which means that the f7-row and its children are not within the oh-link. In the example, all the items that should be contained within the link are indented more than the link component itself.

1 Like

You were right. Now it is working. Thank you for your support:

uid: Fernsehprogramm
tags: []
props:
  parameters:
    - description: Title for the widget
      label: Static Title
      name: title
      required: false
      type: TEXT
    - context: item
      label: Select a 'Fernsehprogramm Group Item'
      name: prefix
      required: true
      type: TEXT
  parameterGroups: []
timestamp: Apr 13, 2021, 9:05:22 PM
component: f7-card
config:
  title: =items[props.prefix+"_Sender"].state
  action: command
  actionItem: Fernsehsender
  actionCommand: =items[props.prefix+"_Sender"].state
slots:
  default:
  
  
    - component: oh-link
    
      config:
        action: command
        actionItem: Fernsehsender
        actionCommand: =items[props.prefix+"_Sender"].state
        
        style:
          width: 100%
      slots:
        default:
        
        - component: f7-card
          config:
            style:
              width: 100%

          slots:
            default:
    
              - component: Label
                config:
                  text: =items[props.prefix+"_Start"].displayState              
                  style:
                    color: rgba(0,200,0,.7)
              - component: Label
                config:
                  text: =items[props.prefix+"_Titel"].state        
                  style:
                    color: rgba(0,200,0,.7)
                  
              - component: Label
                config:
                  style:
                    color: rgba(255,144,0,.7)
                  text: =items[props.prefix+"_Start_Next"].displayState
              - component: Label
                config:
                  style:
                    color: rgba(255,144,0,.7)
                  text: =items[props.prefix+"_Titel_Next"].state


1 Like

Hello,

can i somehow show different icons on a widget depending on the state of an item?

For example i changed from a simple day/night mode to the timeOfDay design pattern of @rlkoshak .
Actual my nightmode at the widget just gets on and off. Now i would like to show a different icon depending on the timeOfDay state (MORNING, DAY, EVENING, BED, NIGHT).

                - component: f7-icon
                  config:
                    f7: moon_zzz_filled
                    item: =props.nachtmodus
                    color: '=(items[props.nachtmodus].state === "ON") ? "yellow" : "gray"'

Is this possible or can i just define two options (condition true/false)?

Thanks, Alex

You can do this in the Same way with the f7 icon like you did with the color, instead of state ON you replace with the time of day state and instead of the color use the f7 icon name. You can have more than 2 options lined up of course.

f7: '=(items[props.timeofday].state === “DAY”) ? “IconA” : (items[props.timeofday].state === “NIGHT”) ? “IconB” : IconC" ’

1 Like

Thank you! I tried this, but get the error, that nested mappings are not allowed in compact mappings:

f7: ‘=(items[props.timeofday].state === “MORNING”) ? “sunrise_fill” : (items[props.timeofday].state === “DAY”) ? “sun_max_fill” : (items[props.timeofday].state === “EVENING”) ? “sunset_fill” : (items[props.timeofday].state === “BED”) ? “bed_double_fill” : (items[props.timeofday].state === “NIGHT”) ? “moon_zzz_filled” : "clear_fill"’

(of course i created the new prop timeofday, too)

Edit: I found the issue, it was the " ’ "

This works fine now:

f7: '=(items[props.timeofday].state === "MORNING") ? "sunrise_fill" : (items[props.timeofday].state === "DAY") ? "sun_max_fill" : (items[props.timeofday].state === "EVENING") ? "sunset_fill" : (items[props.timeofday].state === "BED") ? "bed_double_fill" : (items[props.timeofday].state === "NIGHT") ? "moon_zzz_filled" : "clear_fill"'

yes, i believe it was my copy paste on a mobile, glad you figured it. :slight_smile:

Are there any plans to enable live-rendering of list-type YAML widgets in the dev tool? As someone who’s programming technique basically devolves to “throw it at the wall and see what sticks”, the inability of the dev tool to visualize list-item widgets is making developing new ones (not just copy-pasting code) very difficult for me.