Posting this here, to summarize my findings in case others have the same problem. I could add a documentation PR, but someone more familiar with JS and frontend development should probably look through it first, as this is mostly coded by trial and error, and I don’t really understand what all of this does and how it is connected…
This is a good start to create a minimal card with a simple editor:
https://gist.githubusercontent.com/thomasloven/1de8c62d691e754f95b023105fe4b74b/raw/359d81fc3e78e1f3ec8fd0e7a9701bc738292044/my-custom-card4-with-editor.js
the static get properties ... is important, or else the editor will not work properly.
Copy the code exactly as it is, and do not rename any functions or variables unless you know what you do…
To display a more advanced form than one simple entity, with a look that matches the rest of HA, you can use <ha form>:
Given a yaml-config like this:
entity: light.foo_bar
battery_sensor: sensor.my_battery
show_bars:
- bar1
- bar2
- bar3
- bar4
You can change render() function and, replace Thomas’ return html... with something like
return html`
<ha-form
.hass=${this._hass}
.data=${this._config}
.schema=${[
{name: "entity", selector: { entity: { domain: "light" } }},
{name: "battery_sensor", selector: { entity: { device_class: "battery" } }},
{name: "show_bars", selector: { select: { multiple: true, mode: "list", options: [
{label: "Label 1", value: "bar1"},
{label: "Label 2", value: "bar2"},
{label: "Another Label", value: "bar3"},
{label: "What now?", value: "bar4"},
]}
}}
]}
.computeLabel=${this._computeLabel}
@value-changed=${this._valueChanged}
></ha-form>
`;
}
From what I have learned:
-
.hassanddatamust be set. - I am not sure if the
computeLabelis necessary, but it was in one of the examples, and does not seem to break anything at least… - The
schemais basically a json-representation of a list of selectors: Selectors - Home Assistant-
namemust match the configuration-stanza you want to show - You can modify the labels for the select-options. I have not been able to modify the labels for the other elements.
-
Whenever the form is updated, the function _valueChanged is called with the event as a parameter. The updated config is found under ev.detail.value. Add a simple console.log(ev) to inspect this object further.
Make sure the functon updates this._config with all the new values and emits an event for HA to update and save the config as well:
_valueChanged(ev) {
if (!this._config || !this._hass) {
return;
}
const _config = Object.assign({}, this._config);
_config.entity = ev.detail.value.entity;
_config.battery_sensor = ev.detail.value.battery_sensor;
_config.show_bars = ev.detail.value.show_bars;
this._config = _config;
const event = new CustomEvent("config-changed", {
detail: { config: _config },
bubbles: true,
composed: true,
});
this.dispatchEvent(event);
}
This function can be renamed (in Thomas’ example it is called entityChanged), but make sure you then also change the reference in the html part of the render() functon: @value-changed=${this.WhateverYouCallIt}
Any handling of default values, optional values etc. needs to be done in one or both of “render()” and “_valueChanged()”.
So you can add something like
if (!this._config.hasOwnProperty('show_bars')) {
// Enable all bars by default
this._config.show_bars = default_show_bars;
}
to render() (before the return html obviously).
And/or you can do validations in _valueChanged() and modify the config before it is saved and updated.
Hope someone finds this useful, and please do not hesitate to use this to create documentation PRs. I just don’t feel comfortable doing it without understanding more of what happens in the background here.