Hey @RGroll ,
is there a smart way to transfer the “label” of the “options” directly to a oh-repeater?
… without having to set props in the widget to e.g. VCR=CHROME,DVR=A1 TV,HDP=PS3,SAT/CBL=SAT …
Thank you!
Hey @RGroll ,
is there a smart way to transfer the “label” of the “options” directly to a oh-repeater?
… without having to set props in the widget to e.g. VCR=CHROME,DVR=A1 TV,HDP=PS3,SAT/CBL=SAT …
Thank you!
You want to set sourceType
to itemStateOptions
and the itemOptions
to the name of the item. This yaml
component: f7-segmented
config:
raised: true
slots:
default:
- component: oh-repeater
config:
sourceType: itemStateOptions
itemOptions: name_of_item_with_options
for: option
slots:
default:
- component: oh-button
config:
text: =loop.option.label
action: command
actionItem: name_of_item_with_options
actionCommand: =loop.option.value
raised: true
With an item that has the following options:
produces this series of buttons
*Note the use of the label
and value
properties on the loop object to easily get both the acutal command and the display command.
@JustinG ,
wow! Great stuff!
Let’s take it one step further… would it be even possible to group the options and put e.g. 2 each or 2, 3, 4 in separate repeaters?
This would be very useful, when you have too many options to be displayed in one row…
Thanks.
Yes, but it’s not very elegant.
oh-repeaters
have a filter
option and also give you access to the complete array that is being looped through via the loop.[array name]_source
object. You can combine these two features to selectively display only a portion of the array in a single repeater by filtering on the index in the source object of the current array object. For example:
component: f7-card
config: {}
slots:
content:
- component: oh-repeater
config:
for: fish
sourceType: array
in:
- name: Fish 1
color: Red
- name: Fish 2
color: Blue
filter: loop.fish_source.indexOf(loop.fish)>=1
slots:
default:
- component: Label
config:
text: =loop.fish.name + " = " + loop.fish.color
Produces
And changing the filter to loop.fish_source.indexOf(loop.fish)<1
gets the first half of the array instead:
To get the whole array in two different pieces then you would just need two separate repeaters, one with a <
filter and one with a `>=’ filter.
With a little work you could even make it slightly more responsive comparing the index to an expression instead of a hard coded number.
@JustinG ,
thank you for dropping the idea with filters. You’re right, this is not very elegant…
What about the following… maybe not too elegant either, but quite flexible, I think…
Let’s assume we use MAP transformation and split the 4 entries below to 2 each in 2 separate .map files located in /transform.
Let’s assume the 2 map
files are:
array_1.map
array_2.map
The widget props to which the above file names would be entered are:
- description: Enter file name of array 1
label: Array 1
name: array1
required: false
type: TEXT
- description: Enter file name of array 2
label: Array 2
name: array2
required: false
type: TEXT
As per docs it would require adaptation of:
config:
sourceType: itemStateOptions
to
config:
sourceType: map
But how to make the MAP transformation work inside the oh-repeater?
I guess it would require…
But how?
Thank you.
Hey @maxmaximax
@JustinG already gave you a great answer.
But just out of curiosity, what would you like to do with that splitted array then?
If it’s just about splitting the values from that array in multiple rows, I would recommend using css here instead of doing some fancy oh-repeater logic, which could look like this for example:
component: f7-card
config:
style:
display: grid
grid-template-columns: repeat(4, 1fr)
gap: 10px
slots:
default:
- component: oh-repeater
config:
sourceType: itemStateOptions
itemOptions: testItem
for: option
fragment: true
slots:
default:
- component: oh-button
config:
text: =loop.option.label
action: command
actionItem: testItem
actionCommand: =loop.option.value
raised: true
fill: true
You can configure the number of items per row by changing the number of columns: grid-template-columns: repeat(4, 1fr)
Hey @RGroll
thanks a lot again for guiding me that way!
Yes, it is about distributing to multiple rows.
Your example above will solve the issue when all values/labels are stated in the itemsStateOptions.
I have another case in which lots of individual commands will have to be gathered in the format command = mode in e.g. a map file for MAP transformation.
I figured out that “sourceType: map” is possible.
But how to make the MAP transformation work inside the oh-repeater?
(Maybe I should just use a dummy item for that and go with itemsStateOptions…)
What would you recommend to do?
I don’t think you can access transformation services from here.
But a MAP transform isn’t really what you want anyway, you’ve been distracted by the xxx.map
file looking like a list.
A MAP transform takes a single value as key and returns a single string to you. There’s no way to examine or iterate the lookup file content.
Example mylist.map
ON=green
OFF=red
BANANA=yellow
You’ve got no way to find out the list is ON,OFF,BANANA which I think is what you’re after?
As @rossko57 said, the map transformation of the oh-repeater doesn’t seem like the right choice here.
But try to describe your scenario a bit more, maybe there are other ways to achieve what you’d like to see.
Hey @RGroll ,
I’m working on a widget to control my pretty old (2010) Denon AVR via the Denon/Marantz binding. The binding is very useful, since it allows to send commands via telnet.
There are a few basic channels that also work with my AVR as they are - e.g. Power on/off, volume, input source.
Some of the channels are “Read” channels, such as “Surround Program”.
In order to set the correct Surround Program" I can use a special “Write” channel (general#command).
I have around 15 commands to change the surround mode e.g. MSDOLBY DIGITAL=DOLBY DIGITAL.
I created an item linked to the command channel, I can send individual commands successfully, but when I tried to collect all commands in the items metadata, itemStateOptions didn’t work. I guess I will have to try this again tonight, since this should work.
Hence I have:
Ideally I would like to have an f7-picker to select the correct modes, but f7-picker doesn’t seem to be working in Main UI…
Am I right?
That’s why I would like to distribute buttons to multiple rows… that’s where the MAP transformation could have helped. I understood from @rossko57 and you that this is not possible.
Your suggestion…
in combination with the above from @JustinG is the smartest way to solve the issue = already solved for 8x Input source.
I will need to get the command issue for the surround program with itemsStateOptions working.
Will try this later today…
Thanks.
Hey @RGroll ,
Would this work with f7-segmented for every row as well?
I don’t think so, but I wanted to doublecheck with you.
Thank you.
The oh-repeater iterates over each item and grabs it’s metadata - so it’s not a problem to grab all of them.
The function is part of the oh/f7-input component but you can’t pass arguments to it right now afaik, so yes, it’s not usable atm.
But there are alternatives like:
Selection list in a separate popup - better for a lot of items and more mobile friendly (similar to the UI configuration selection)
uid: selection_type-1
component: f7-card
config:
title: "Selection type #1"
slots:
default:
- component: f7-row
config:
class:
- padding
slots:
default:
- component: oh-repeater
config:
sourceType: array
for: selection
in:
- title: Input source
icon: f7:tv
item: testItem
- title: Surround programs
icon: f7:music_note_list
item: testItem5
fragment: true
slots:
default:
- component: f7-col
slots:
default:
- component: oh-list
config:
id: list
slots:
default:
- component: oh-list-item
config:
title: =loop.selection.title
after: =items[loop.selection.item].displayState
smartSelect: true
icon: =loop.selection.icon
iconColor: default
popupOpen: =".selectionPopup_"+loop.selection_idx
style:
border: 1px solid lightgray
border-radius: 5px
- component: f7-popup
config:
class: ="selectionPopup_"+loop.selection_idx
slots:
default:
- component: f7-page
slots:
default:
- component: f7-navbar
config:
title: =loop.selection.title
style:
position: sticky
slots:
left:
- component: oh-link
config:
iconIos: f7:arrow_left
iconMd: material:arrow_back
iconAurora: f7:arrow_left
popup-close: true
- component: f7-list
config:
virtualList: true
slots:
default:
- component: oh-repeater
config:
sourceType: itemStateOptions
itemOptions: =loop.selection.item
for: option
fragment: true
slots:
default:
- component: oh-list-item
config:
title: =loop.option.label
actionFeedback: ='{ "text":"You selected <b>' + loop.option.label + '</b><br>Sending command <b>' + loop.option.value + '</b> to item", "position":"center","icon":"<i style=\\"color:green\\" class=\\"f7-icons\\">checkmark_alt</i>","closeButton":true }'
noChevron: true
radio: true
checked: "=loop.option.value === items[loop.selection.item].state ? true : false"
popupClose: true
action: command
actionItem: =loop.selection.item
actionCommand: =loop.option.value
uid: selection_type-2
component: f7-card
config:
title: "Selection type #2"
slots:
default:
- component: f7-card
config:
noShadow: true
class:
- no-margin
slots:
default:
- component: f7-card-content
config:
class:
- margin-top-half
slots:
default:
- component: f7-list
slots:
default:
- component: f7-list-item
config:
title: Input source
after: =items.YOUR_SOURCE_ITEM.state
- component: f7-list-item
config:
title: Surround programs
after: =items.YOUR_SURROUND_ITEM.state
- component: f7-row
config:
class:
- padding
- padding-top-half
slots:
default:
- component: f7-col
slots:
default:
- component: oh-button
config:
text: Input source
outline: true
action: options
actionItem: YOUR_SOURCE_ITEM
- component: f7-col
slots:
default:
- component: oh-button
config:
text: Surround programs
outline: true
action: options
actionItem: YOUR_SURROUND_ITEM
It is (I think) - but it would be too easy giving you a solution, so I think this is a good challenge for you, if the above variants doesn’t fit your needs.
Hey @RGroll ,
learning a lot - tried all options, got most of it working even f7-segmented, but your method is much nicer
Got a small challenge with…
Working fine with item name:
- component: oh-repeater
config:
sourceType: array
for: selection
in:
- title: Surround programs
icon: f7:music_note_list
item: DenonAVR4310_SendSurroundProgram
… not working with props even though I’m using exactly the same props successfully in other places:
- component: oh-repeater
config:
sourceType: array
for: selection
in:
- title: Surround programs
icon: f7:music_note_list
item: =props.itemSendSurroundProgramCommand
Why is that?
Shouldn’t it be possible to use expressions within an array?
Thanks.
The map
parameter in the oh-repeater
is not about the map transformations in your config folders, that’s just a coincidence of terminology.
map
is not an accepted value for the ‘sourceType’ parameter:map
refers to in this case is an expression that can be applied to each value in the repeater’s array (after the filter is applied) that transforms the final element value. My small example widget from above could achieve exactly the same results using the map
parameter to do the string building instead of doing it at the level of the label text:component: f7-card
config: {}
slots:
content:
- component: oh-repeater
config:
for: fish
sourceType: array
in:
- name: Fish 1
color: Red
- name: Fish 2
color: Blue
filter: loop.fish_source.indexOf(loop.fish)>=1
map: loop.fish.name + " = " + loop.fish.color
slots:
default:
- component: Label
config:
text: =loop.fish
This is a bit OT…
Tried to find a way to add a horizontal line as a divider or separator and just found the following which is probably a bit of a tweak rather than a good solution:
- component: f7-card
config:
outline: true
showing up in the UI:
Is there a more elegant way to add horizontal lines?
Thanks.
Can’t say if it’s a bug or a known limitation, but It’s exactly that - expressions does not work inside the oh-repeater
array definition. You could open an issue for that on the webui repo on github.
maybe a bit OT, but still related to the oh-repeater topic…
I’m struggeling with switching visibility of one widget from another widget…
Let’s assume I have 2 widgets:
Dashboard1
Dashboard2
What would I like to achieve:
Visibility of Dashboard2 should be triggered from a button residing inside an oh-repeater of Dashboard1
- component: oh-repeater
config:
sourceType: array
for: control
in:
- icon: lightbulb
option: light
- icon: electrical_services
option: socket
- icon: storefront
option: markise
- icon: music_video
option: tv_av
fragment: true
slots:
default:
- component: oh-button
config:
icon-material: =loop.control.icon
iconSize: 30px
fill: "=vars[loop.control.option] || vars[loop.control.option] === undefined ? false : true"
outline: true
class:
- padding-top-half
- padding-bottom-half
- display-flex
- flex-direction-column
style:
--f7-button-border-color: var(--f7-card-outline-border-color)
height: 52px
action: variable
actionVariable: =loop.control.option
actionVariableValue: "=vars[loop.control.option] || vars[loop.control.option] === undefined ? false : true"
I’d like to use “option: tv_av” from the array to trigger visibility of Dashboard2.
- component: oh-grid-col
config:
medium: "33"
width: "100"
slots:
default:
- component: widget:Dashboard1
config:
title: Dashboard1
- component: oh-grid-col
config:
medium: "33"
width: "100"
slots:
default:
- component: widget:Dashboard2
config:
visibility: ??????????
title: Dashboard2
How to get this done?
You can use the widget vars
object to pass values between different components within a widget. OH components with actions will have the variable
option to set a variable value that can then be accessed in expressions throughout the widget. Here’s an example that uses two button created by a repeater to set two different variables to control the visibility of two different labels.
uid: widget_vars_demo
component: f7-card
config: {}
slots:
default:
- component: f7-row
config: {}
slots:
default:
- component: f7-col
config: {}
slots:
default:
- component: oh-repeater
config:
for: visButton
in:
- label: Dash 1
visibility: someWidget
- label: Dash 2
visibility: someOtherWidget
fragment: true
slots:
default:
- component: oh-button
config:
raised: true
text: =loop.visButton.label
action: variable
actionVariable: =loop.visButton.visibility
actionVariableValue: =!vars[loop.visButton.visibility]
- component: f7-col
config: {}
slots:
default:
- component: Label
config:
text: First Dash Widget
visible: =!vars.someWidget
- component: Label
config:
text: Second Dash Widget
visible: =!vars.someOtherWidget
Hey @JustinG ,
Yes, I am aware of the above described solution.
Thank you.
However, I’m looking for a solution to do this across widgets = on widget level instead of “component within a widget”.
(button in widget “Dashboard” triggers visibility of widget “Dreambox DM8000”)
How to get this done?