Question/Feature request: joining entity attributes in one column?
pejotigrek opened this issue · comments
I'm playing with your custom card to make a table that lists some part of my devices, checking it's state
, last_changed
date & time etc. and because I want to put it in popup window, in lovelace ui that's designed for phone screens, I have kinda limited space ;)
so right now it's easy to have a regular table, one attribute for a column:
Device | State | Change | EntityID |
---|---|---|---|
friendly name | online | 2020-02-01, 17:00 | device.some_name |
and I can of course change color of state
text based on it's,, state :) so I have green online and red-background, white-letters offline.
now things are getting tricky, as I wanted to do something like this:
Device | Change |
---|---|
friendly name / device.some_name | 2020-02-01, 17:00 |
where device.some_name
is displayed as a secondary line below the friendly_name
and additionaly if device is offline, I'd like to change the friendly_name
's color to red.
while I know how to concatenate or replace strings to have two lines of text, or to change some color, I'm having troubles with figuring out how to configure column so I can put name
and entity_id
together in one.
first I thought that attr_as_list
is what I'm looking for but either I can't understand the proper usage, or it isn't that.
ok, so after this long introduction:
- if
attr_as_list
is the solution can you please point me to the right direction, giving an example of combiningstate
&last_changed
with "regular attributes" (like those visible in the developer/state tab) - in one column? - if
attr_as_list
is not the solution - do you think it would be plausible to add that feature?
phew, I'm only hoping, that I didn't complicate the above post/question - english isn't my first language and while I'm 100% sure what I wanted to say/wrote, I'm not that sure I correctly wrote that down ;)
This is more or less why attr_as_list
does exist, allowing to put arbitrary content into each row and cell. Basically I do this using the custom-component variables
: https://github.com/snarky-snark/home-assistant-variables, which is filled with the appropriate data by appdaemon using the service provided by the variable component.
Overall the idea was to not get too complex on frontend side, usually I do prefer data-manipulation/assembly to be not part of the frontend. Therefore attr_as_list
was invented to allow an arbitrary backend to assemble some data, fill it into some variable's attributes and then simply show it.
Nonetheless, questionable would be "how much data-manipulation on frontend side is too much?". Tricky one, e.g., #21 and #20 are also requesting a similar (merging or css-on-content-condition) feature. Maybe already allowing merging of columns, like this: merge_col: <column-id>
might already solve most use-cases.
Further "conditional css-properties based on cell-contents" is quite ugly to generalize, but one could merge the Device
and State
column and then use modify:
to run js-code in order to change the color of the cell, but merge_col
is for sure necessary before that ...
well, merge_col
is maybe the wrong approach, how about the possibility to select multiple attributes/properties into a single cell, likely far better than merging it afterwards. Will have to think about the col-config to enable that, currently not so obvious... let's see...
Using this approach here, you should get multiple cells "merged" or selected together.
type: 'custom:flex-table-card'
title: Power Consumption (Top 10)
columns:
- attr: node_id
name: NodeID
- attr: power_consumption
name: Power
- name: Energy
prop: state
- name: My Multi-Item-Field
multi_delimiter: ','
multi:
- - attr
- node_id
- - attr
- power_consumption
- [prop, state] /* <-- means the same, but looks prettier... */
entities:
include: 'sensor.*_energy(_[0-9]+)?'
multi
just serves as a list of multiple entries for data selection. Due to backwards-compatibility I have to do this with a separate multi
config property. The selected cell contents are acquired and finally get concatenated using the delimiter ' ' (whitespace) by default. You might change this default behavior by setting multi_delimiter
to an arbitrary string.
Once you have this, it's quite straight forward to color cells based on their content. Just use something similar to #20 using modify
. You might insert a <span>
and set the cell-css-class like this:
modify: '(x.split(",")[0] == "some condition") ?
x.split(",")[1] :
`<span class=font_color_blue>${x.split(",")[1]}</span>`'
Of course, you might also just set the css-style via js directly, whatever serves. But yes, we are reaching a point, where one might question whether this is really the correct approach for doing something like this.
Anyways, hope it works, cheers
whoa! thanks for such a long and informative answers!
I surely must take a look on that with clear mind to understand everything correctly & try to implement in my scenario. I hope it won't take too much time for me and I'll be able to report here if I succeed or not ;)
on a side not - about the variables component - I use another custom component for variables support, but I get the idea. "problem" is that I'm also trying not to duplicate any entities, and since few weeks I'm trying to phase out that component. meaning: if there's an entity with some attribute, I am not too happy to create another entity that would just keep the old entity's attribute, if you know what I mean ;) sure, if there's no other solution and everything else fails I'll bite the bullet, but it's not a desired solution [for me ofcourse].
if there's an entity with some attribute, I am not too happy to create another entity that would just keep the old entity's attribute, if you know what I mean ;)
I totally know what you mean, especially if you handle more than a handful of devices within your smart home, any double book-keeping is painful and error-prone. But I think flex-table-card
should now give you capabilities to realize your initial ideas - post a screenshot on success if possible.
ok, I can tell that last card update works great!
code/design is still under construction, but first draft looks very promising :)
I'm using this code:
- type: custom:flex-table-card
sort_by: friendly_name+
clickable: true
css:
table+: "border: 0; border-collapse: collapse;"
table: "font-size: 0.85em;"
'tbody tr:nth-child(even)': "background-color: transparent;"
'tbody tr td': "padding-top: 2px; padding-bottom: 2px; border-top: 1px dotted var(--primary-text-color);"
entities:
include:
- device_tracker.png_soa*
- device_tracker.png_esp*
columns:
- name: Urządzenie
icon: mdi:power-settings
multi_delimiter: "|"
multi:
- [attr, state]
- [attr, friendly_name]
modify: '((x.split("|")[0] == "online") ? `<span style="color:#138535;">${x.split("|")[1]}</span>` : `<span style="color:#FFF;background:#F00;">${x.split("|")[1]}</span>`)'
- prop: last_changed
icon: mdi:calendar-check
modify: (x.split("T")[0].concat(", ")).concat(x.split("T")[1].split(".")[0][0]).concat(x.split("T")[1].split(".")[0][1]).concat(x.split("T")[1].split(".")[0][2]).concat(x.split("T")[1].split(".")[0][3]).concat(x.split("T")[1].split(".")[0][4])
- prop: entity_id
icon: mdi:textbox
modify: x.replace("device_tracker.", "")
prefix: "<span style='font-style: oblique; color: var(--secondary-text-color)'>"
suffix: "</span>"
above table shows my ESP-based devices [sockets, switches etc.] and their online/offline status, status last changed time and entity id for easy config search. this is kinda system/debug cart that I use from time to time when looking for issues [which device went offline/has connection problems etc.], so it meant to be technical :)
thanks for update and all the hints!
hmmm, I've noticed that there's some isssu with sorting - it isn't sorted by friendly_name
as configured in the code. did I missed something?
This looks very promising, nice collection of ESP devices 🤓
Concerning the sort_by
issue. The to-be-sorted column is identified using the provided sort_by
value, in this case friendly_name+
. Under the hood any matching value from id, attr, prop, attr_as_list
is considered enough.
Keep in mind that sorting is based on final cell contents (excl. prefix
, suffix
), after modify
evaluated, so consider including a hidden column, if you struggle with the sorting.
Your columns names/ids are:
Urządzenie
(name)last_changed
(prop)entity_id
(prop)
So none of them is matching with friendly_name+
, try to simply set id: friendly_name
for the column you would like to sort, should do the job...
cheers
thanks! now, seeing that collection & keeping in mind that I'll have about 2-3 tables more, it is certain why I wasn't too happy to add some variable entities with attributes haha ;)
regarding the sorting issue - I get it! didn't thought about this. I'll just add a hidden column then. no problem :)
ok, I can confirm, adding and hiding another column was enough :)
after adding friendly_name
as first column, I also added this line to css:
'thead tr th:first-child, tbody tr td:first-child': "display: none;"
and everything looks like it meant to :)
so for now - my problem is solved, I'm closing it :) thank you!
Always good to hear, you're very welcome...
Apart from that, hiding columns is out-of-the-box possible using the hidden: true
configuration property within one column's sub-config. (This is a bad moment for the documentation, I know much to do there)
cheers
hah! I had my yaml-momentum going and didn't even thought that hiding columns will be in the docs.. cool, I'll exchange my css to native solution :) thanks again :)
@daringer I don't want yet to reopen this, or make another one topic, but suddenly the "main" line:
modify: '((x.split(",")[0] == "online") ? `<span style="color:#138535;">${x.split("|")[1]}</span>` : `<span style="color:#FFF;background:#F00;">${x.split("|")[1]}</span>`)'
is giving me "undefined", while [attr, state]
and [attr, friendly_name]
are outputting proper data.
component installed: version 13960ca
This very commit: 13960ca is when "strict" mode is active for the custom-card at least. You could first try to confirm this reason by simply setting type: module
back to type: js
within your lovelace config. If you don't see the undefined case popping up anymore you've found the reason.
JS-strict mode will not allow all the dirty js things the internet has taught us.
I would suggest setting some example "x"s within the chromium console and simply execute the modify line.
unfortunately bringing back type: js
didn't helped :(
where can I change this "strict" setting?
nevermind.
there must have been some syntax error in the troubled line. I've made a copy-and-paste fix using another table which displays other devices in the very same way - and it started working. don't know how did it happened, as the first line was a source of every other table, but now it's fixed. sorry for bothering you ;(