From 78b796449a887824a4438111be37d9c73acec4b2 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 26 Jan 2019 11:33:17 -0800 Subject: [PATCH] Update custom card config example --- docs/lovelace_custom_card.md | 4 +- website/i18n/en.json | 3 + .../version-0.86.0/lovelace_custom_card.md | 211 ++++++++++++++++++ 3 files changed, 216 insertions(+), 2 deletions(-) create mode 100644 website/versioned_docs/version-0.86.0/lovelace_custom_card.md diff --git a/docs/lovelace_custom_card.md b/docs/lovelace_custom_card.md index 73f007fe..9adfca93 100644 --- a/docs/lovelace_custom_card.md +++ b/docs/lovelace_custom_card.md @@ -87,7 +87,7 @@ customElements.define('content-card-example', ContentCardExample); In our example card we defined a card with the tag `content-card-example` (see last line), so our card type will be `custom:content-card-example`. And because you created the file in your `/www` directory, it will be accessible in your browser via the url `/local/` (if you have recently added the www folder you will need to re-start home assistant for files to be picked up). ```yaml -# Example ui-lovelace.yaml +# Example Lovelace configuration resources: - url: /local/content-card-example.js type: js @@ -194,7 +194,7 @@ customElements.define('wired-toggle-card', WiredToggleCard); And for your configuration: ```yaml -# Example ui-lovelace.yaml +# Example Lovelace configuration resources: - url: /local/wired-cards.js type: module diff --git a/website/i18n/en.json b/website/i18n/en.json index 3a79d2e8..966c9144 100644 --- a/website/i18n/en.json +++ b/website/i18n/en.json @@ -1075,6 +1075,9 @@ }, "version-0.86.0-hassio_addon_config": { "title": "Add-On Configuration" + }, + "version-0.86.0-lovelace_custom_card": { + "title": "Lovelace: Custom Cards" } }, "links": { diff --git a/website/versioned_docs/version-0.86.0/lovelace_custom_card.md b/website/versioned_docs/version-0.86.0/lovelace_custom_card.md new file mode 100644 index 00000000..1dd444ce --- /dev/null +++ b/website/versioned_docs/version-0.86.0/lovelace_custom_card.md @@ -0,0 +1,211 @@ +--- +title: "Lovelace: Custom Cards" +id: version-0.86.0-lovelace_custom_card +original_id: lovelace_custom_card +--- + +[Lovelace](https://www.home-assistant.io/lovelace/) is our new approach to defining your user interface for Home Assistant. We offer a lot of built-in cards, but you're not just limited to the ones that we decided to include in the Lovelace UI. You can build and use your own! + +## API + +You define your custom card as a [custom element](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements). It's up to you to decide how to render your DOM inside your element. You can use Polymer, Angular, Preact or any other popular framework (except for React – [more info on React here](https://custom-elements-everywhere.com/#react)). + +```js +const element = document.createElement('some-custom-card'); +``` + +Home Assistant will call `setConfig(config)` when the configuration changes (rare). If you throw an exception if the configuration is invalid, Lovelace will render an error card to notify the user. + +```js +try { + element.setConfig(config); +} catch (err) { + showErrorCard(err.message, config); +} +``` + +Home Assistant will set the `hass` property when the state of Home Assistant changes (frequent). Whenever the state changes, the component will have to update itself to represent the latest state. + +```js +element.hass = hass; +``` + +Your card can define a `getCardSize` method that returns the size of your card as a number. A height of 1 is equivalent to 50 pixels. This will help Home Assistant distribute the cards evenly over the columns. A card size of `1` will be assumed if the method is not defined. + +```js +if ('getCardSize' in element) { + return element.getCardSize(); +} else { + return 1; +} +``` + +## Defining your card + +Create a new file in your Home Assistant config dir as `/www/content-card-example.js` and put in the following contents: + +```js +class ContentCardExample extends HTMLElement { + set hass(hass) { + if (!this.content) { + const card = document.createElement('ha-card'); + card.header = 'Example card'; + this.content = document.createElement('div'); + this.content.style.padding = '0 16px 16px'; + card.appendChild(this.content); + this.appendChild(card); + } + + const entityId = this.config.entity; + const state = hass.states[entityId]; + const stateStr = state ? state.state : 'unavailable'; + + this.content.innerHTML = ` + The state of ${entityId} is ${stateStr}! +

+ + `; + } + + setConfig(config) { + if (!config.entity) { + throw new Error('You need to define an entity'); + } + this.config = config; + } + + // The height of your card. Home Assistant uses this to automatically + // distribute all cards over the available columns. + getCardSize() { + return 3; + } +} + +customElements.define('content-card-example', ContentCardExample); +``` + +## Referencing your new card + +In our example card we defined a card with the tag `content-card-example` (see last line), so our card type will be `custom:content-card-example`. And because you created the file in your `/www` directory, it will be accessible in your browser via the url `/local/` (if you have recently added the www folder you will need to re-start home assistant for files to be picked up). + +```yaml +# Example Lovelace configuration +resources: + - url: /local/content-card-example.js + type: js +views: +- name: Example + cards: + - type: "custom:content-card-example" + entity: input_boolean.switch_tv +``` + +## Advanced example + +Resources to load in Lovelace can be imported as a JS script, an HTML import or as a JS module import. Below is an example of a custom card using JS modules that does all the fancy things. + +![Screenshot of the wired card](/img/en/frontend/lovelace-ui-custom-card-screenshot.png) + +Create a new file in your Home Assistant config dir as `/www/wired-cards.js` and put in the following contents: + +```js +import 'https://unpkg.com/wired-card@0.6.5/wired-card.js?module'; +import 'https://unpkg.com/wired-toggle@0.6.5/wired-toggle.js?module'; +import { + LitElement, html +} from 'https://unpkg.com/@polymer/lit-element@^0.5.2/lit-element.js?module'; + +function loadCSS(url) { + const link = document.createElement('link'); + link.type = 'text/css'; + link.rel = 'stylesheet'; + link.href = url; + document.head.appendChild(link); +} + +loadCSS('https://fonts.googleapis.com/css?family=Gloria+Hallelujah'); + +class WiredToggleCard extends LitElement { + static get properties() { + return { + hass: Object, + config: Object, + } + } + + _render({ hass, config }) { + return html` + + + ${config.entities.map(ent => hass.states[ent]).map((state) => + html` +
+ ${state.attributes.friendly_name} + +
+ ` + )} +
+ `; + } + + setConfig(config) { + if (!config.entities) { + throw new Error('You need to define entities'); + } + this.config = config; + } + + // The height of your card. Home Assistant uses this to automatically + // distribute all cards over the available columns. + getCardSize() { + return this.config.entities.length + 1; + } + + _toggle(state) { + this.hass.callService('homeassistant', 'toggle', { + entity_id: state.entity_id + }); + } +} +customElements.define('wired-toggle-card', WiredToggleCard); +``` + +And for your configuration: + +```yaml +# Example Lovelace configuration +resources: + - url: /local/wired-cards.js + type: module +views: +- name: Example + cards: + - type: "custom:wired-toggle-card" + entities: + - input_boolean.switch_ac_kitchen + - input_boolean.switch_ac_livingroom + - input_boolean.switch_tv +```