Today another user reported errors while installing my widget via the UI.
We tried to debug this, but I realized something must be broken since OH 3.1.
I used a conversion pattern
- component: Label
config:
pattern: %1$tM:%1$tS
to convert seconds to a user readable minutes:seconds
this worked in OH 3.1 but now the logs the user provided show this
2022-03-30 10:02:40.898 [ERROR] [munity.CommunityUIWidgetAddonHandler] - Unable to parse YAML: while scanning for the next token
found character '%' that cannot start any token. (Do not use % for indentation)
in 'reader', line 179, column 30:
pattern: %1$tM:%1$tS
^
at [Source: (StringReader); line: 179, column: 28] (through reference chain: org.openhab.core.ui.components.RootUIComponent["slots"]->java.util.LinkedHashMap["default"]->java.util.ArrayList[5]->org.openhab.core.ui.components.UIComponent["slots"]->java.util.LinkedHashMap["default"]->java.util.ArrayList[0]->org.openhab.core.ui.components.UIComponent["slots"]->java.util.LinkedHashMap["default"]->java.util.ArrayList[0]->org.openhab.core.ui.components.UIComponent["config"])
2022-03-30 10:02:40.900 [ERROR] [munity.CommunityUIWidgetAddonHandler] - Widget from marketplace is invalid: Unable to parse YAML
he wasnāt able to install the widget via mainUI on openHAB 3.3.0~S2833-1
I edited the line to the following
pattern: "%1$tM:%1$tS"
After the change Iām able to install the widget from mainUI, but the TrackDuration isnāt shown anymore with the edited pattern.
I also tried changing the pattern to a JS transformation
pattern: JS(mmss.js):%s
and added a js file in the transform folder but the Duration isnāt shown either.
I donāt know how this could happen?!?
Are there any changes made on parsing the pattern declaration? Any changes in yaml syntax?
Any help appreciated. I tested this today on openHAB 3.3.0.M2
To be honest, I donāt believe that this ever worked to begin with. The only thing that I think has changed with regard to labels is that thereās better linting so errors like this are now caught when previously they were more readily ignored.
If Iām not mistaken, the full component that you are referring to is:
The text that you are supplying to the label is the itemās displayState which means that there may already be a pattern applied if there is one defined for the item in the StateDescription metadata.
Secondly, if you look at where the Label component is created in the UI source code, itās a very simplistic component.
You can see that all it does is directly pass the text config parameter to the content of a div block and apply the style and class config parameters to the div. Thereās no processing of the text and that hasnāt changed. I could be wrong, but as far as I know a pattern config value has never been parsed for the labels.
thanks for your reply
even if it surprises me a bitā¦
as you can see in my screenshot it was working when I developed the custom widget.
I must admit, initially I used the JS conversion as pattern and not the other one to be honestā¦
but if youāre right and this wouldnāt work at all - the only possibility would be that the Item itself converted it, as you stated above if I get that rightā¦
A few weeks ago I converted my items from files to UI, so Iām not able to confirm thisā¦
What I can see is that none of my UI items have a conversion scheme in the ānameā now.
Do you think thereās a way to achieve the conversion via the widget?
Edit:
I added the JS conversion via state description for testing purposes this seems to work.
but it would be nice to convert the values in the widget so that users donāt have to add the conversion to all their duration itemsā¦
Ah yes. That makes everything more clear. In deed. When you had item files with the pattern in the label definition those patterns where converted to the state description metadata so that is what was being displayed by the call to displayState in the widget. When you converted to the UI items, which, as you noted, donāt take the pattern in the label anymore then you lost that formatting information, and have to manually add it to the metadata.
Certainly. The label text does get parsed through the expression parser so you can use JS expressions to format the label directly. So you should be able to adapt what you have in your transform file directly into the label line using the item state (not displayState) in place of your transform function variable.
yes but the funny thing is, I have other UI converted items that had a conversion pattern in the label, and theyāre still there ā¦so this looks like I never converted via Item in this case?!?
or some item were converted in another way - but that sounds weird to meā¦ theyāre all imported to UI in the same way.
very mysterious
Ok any hint how this would look like? I donāt really get what you mean exactlyā¦
this isnāt working - maybe you have an idea what I can do for a workaround? (linebreaks only for the readability)
this is the error:
Nested mappings are not allowed in compact mappings at line 241, column 15:
text: "=(Math.trunc(Number(items[props.prefix+items[props.selected].staā¦
^
EDIT: Iāve read a lot about Number and Math objects in javascript, but found no solution. Can you explain what is a ācompact mapping/nested mappingā Iāve found no info so farā¦
This is not a javascript error, this is a yaml error. This results from an unfortunate collision of using some js syntax inside yaml. The js ternary expression (boolean test) ? result if true : result if false uses a colon, but a colon is a reserved character for yaml to separate the key name and the value, so if you have an colon in the middle of the yaml value the yaml parser thinks you are trying to define another key/value pair inside the first one (nesting mapping) while putting it all on one line. The solution to this is to make sure that if you have a colon in your value you wrap the entire value in āā¦ā or āā¦ā so that the yaml parser knows the colon is just part of a string and not an attempt to map a value. You can do this even for entire expressions (anything in the widget definition that starts with an =). The only trick to remember is that if you already have one type of quotes in the expression for some string value you have to wrap the whole expression in the other type of quote. So, for any of the ternary expressions in the widgets is goes somthing like this:
key: "=(boolean test) ? 'string if true' : 'string if false'"
Fortunately, we donāt have to worry about using the ternary expression in this case. JS has built-in methods for padding strings. In this case you want to pad the front of the string with a zero so you use the padStart method. padStart is, however a string method, so we have to make sure that we convert our number into a string first:
ā¦this is all relatively new to me - but I think I got what you explained.
I will try out this padstart method and read a little bit more about the use of js
Iām very happy that you had the time to explain this - thanx a ton!