Hi all,
Does anyone know how to reuse layout yaml code across different views without having to copy and paste the full (in my case 39) lines of code?
I have the following code in my yaml code:
layout:
margin: 0
grid-gap: 10px
grid-template-columns: 200px repeat(3, 1fr) 0fr
grid-template-rows: 55px repeat(3, fit-content(100%)) 55px
grid-template-areas: |
"sidebar header header header ."
"sidebar info info info ."
"sidebar left middle right ."
"sidebar left2 middle2 right2 ."
"servers servers people internet ."
mediaquery:
'(max-width: 650px)':
grid-template-columns: auto
grid-template-rows: 100%
grid-template-areas: |
"sidebar"
"header"
"info"
"people"
"middle"
"left"
"right"
"left2"
"middle2"
"right2"
"servers"
"internet"
'(max-width: 1600px)':
grid-gap: 5px
grid-template-columns: 100px repeat(3, 1fr) 0fr
grid-template-rows: 40px repeat(3, min-content) 55px auto
grid-template-areas: |
"sidebar header header header ."
"sidebar info info info ."
"sidebar left middle right ."
"sidebar left2 middle2 right2 ."
". servers people internet ."
". . . . ."
Ideally this would be reused across all views as i have a set layout that i’d like to use across all views. If i make a change, I would rather not have to amend this code across all views.
I have tried to use !include and split this into a different yaml file but it doesn’t appear to be formatting my cards correctly - however using the exact code in the main yaml file it does render correctly so I don’t think it is incorrect yaml.
Any help would be much appreciated.
James
petro
(Petro)
August 7, 2023, 11:24am
2
Typically you can only reuse things with yaml mode & anchors. Otherwise it’s copy paste. There custom cards like decluttering card that also do this. But again, I don’t believe you can use that in the UI.
Yeah, i have had a look at decluttering cards but i don’t think works with the main layout part of the lovelace views.
I’ve not looked at anchors before - would that enable me to copy the above layout yaml and reuse it in other views within the same file?
petro
(Petro)
August 7, 2023, 11:41am
4
Yes, if you put all of your yaml into a single file. But you cannot use the UI at all . It has to be 100% yaml only mode.
Is it about using a “custom:layout-card” ?
I’ve been building it all in YAML anyway, so not using the UI is not an issue.
So if i understand it right, would i just change the first “layout:” to “&layout:”
and then whenever i have a layout: for a different view further down the file change that to “*layout:” and it would then use the first section of code as below:
&layout:
margin: 0
grid-gap: 10px
grid-template-columns: 200px repeat(3, 1fr) 0fr
grid-template-rows: 55px repeat(3, fit-content(100%)) 55px
grid-template-areas: |
"sidebar header header header ."
"sidebar info info info ."
"sidebar left middle right ."
"sidebar left2 middle2 right2 ."
"servers servers people internet ."
mediaquery:
'(max-width: 650px)':
grid-template-columns: auto
grid-template-rows: 100%
grid-template-areas: |
"sidebar"
"header"
"info"
"people"
"middle"
"left"
"right"
"left2"
"middle2"
"right2"
"servers"
"internet"
'(max-width: 1600px)':
grid-gap: 5px
grid-template-columns: 100px repeat(3, 1fr) 0fr
grid-template-rows: 40px repeat(3, min-content) 55px auto
grid-template-areas: |
"sidebar header header header ."
"sidebar info info info ."
"sidebar left middle right ."
"sidebar left2 middle2 right2 ."
". servers people internet ."
". . . . ."
Rudd-O
(Rudd-O)
August 8, 2023, 12:59am
7
Can I have your full code please? I want to test your dashboard.
This is all i have at the moment - so please be aware it is unfinished. I am still building it out and trying to overcome the multi-view and layout templating.
resources:
- url: /local/decluttering-card.js
type: module
decluttering_templates: !include decluttering_templates.yaml
views:
- title: Home
type: custom:grid-layout
path: home
icon: mdi:home-assistant
layout:
margin: 0
grid-gap: 10px
grid-template-columns: 200px repeat(3, 1fr) 0fr
grid-template-rows: 55px repeat(3, fit-content(100%)) 55px
grid-template-areas: |
"sidebar header header header ."
"sidebar info info info ."
"sidebar left middle right ."
"sidebar left2 middle2 right2 ."
"servers servers people internet ."
mediaquery:
'(max-width: 650px)':
grid-template-columns: auto
grid-template-rows: 100%
grid-template-areas: |
"sidebar"
"header"
"info"
"people"
"middle"
"left"
"right"
"left2"
"middle2"
"right2"
"servers"
"internet"
'(max-width: 2600px)':
grid-gap: 5px
grid-template-columns: 100px repeat(3, 1fr) 0fr
grid-template-rows: 40px repeat(3, min-content) 55px auto
grid-template-areas: |
"sidebar header header header ."
"sidebar info info info ."
"sidebar left middle right ."
"sidebar left2 middle2 right2 ."
". servers people internet ."
". . . . ."
cards:
- type: custom:decluttering-card ### Sidebar ###
template: sidebar_template
view_layout:
grid-area: sidebar
- type: custom:decluttering-card ### Header ###
template: header_template
view_layout:
grid-area: header
- type: custom:decluttering-card ### Info ###
template: info_template
view_layout:
grid-area: info
- type: vertical-stack
cards:
- show_name: true
show_icon: true
type: button
tap_action:
action: navigate
navigation_path: home-assistant
icon: mdi:home-assistant
show_state: true
icon_height: 35px
name: Home Assistant Status
- show_name: true
show_icon: true
type: button
tap_action:
action: navigate
navigation_path: home-lights
icon: mdi:home-lightbulb
show_state: true
icon_height: 35px
name: Lights
view_layout:
grid-area: left
- type: vertical-stack
cards:
- initial_view: dayGridDay
type: calendar
entities:
- calendar.home_home
- calendar.bins_bins
- calendar.uk_holidays
view_layout:
grid-area: middle
- type: vertical-stack
cards:
- type: conditional
conditions:
- entity: switch.pi_hole
state_not: unavailable
card:
show_name: true
show_icon: true
type: button
tap_action:
action: call-service
service: pi_hole.disable
data:
duration: '00:05:00'
target:
entity_id:
- switch.pi_hole
- switch.pi_hole_mac_mini
entity: switch.pi_hole
name: TrueNAS Pihole blocking is
hold_action:
action: none
show_state: true
icon_height: 50px
- type: conditional
conditions:
- entity: switch.pi_hole_mac_mini
state_not: unavailable
card:
show_name: true
show_icon: true
type: button
tap_action:
action: call-service
service: pi_hole.disable
data:
duration: '00:05:00'
target:
entity_id:
- switch.pi_hole_mac_mini
- switch.pi_hole
entity: switch.pi_hole_mac_mini
name: Mac Mini Pihole blocking is
hold_action:
action: none
show_state: true
icon_height: 50px
- show_name: true
show_icon: true
show_state: true
type: glance
entities:
- entity: switch.pi_hole
- entity: switch.pi_hole_mac_mini
state_color: true
view_layout:
grid-area: right
- type: custom:decluttering-card ### Footer Server ###
template: server_footer_template
view_layout:
grid-area: servers
- type: custom:decluttering-card ### Footer People ###
template: people_footer_template
view_layout:
grid-area: people
- type: custom:decluttering-card ### Footer Internet ###
template: internet_footer_template
view_layout:
grid-area: internet
- title: Rooms
type: custom:grid-layout
path: rooms
icon: mdi:room-service
subview: true
layout:
margin: 0
grid-gap: 10px
grid-template-columns: 200px repeat(3, 1fr) 0fr
grid-template-rows: 55px repeat(3, fit-content(100%)) 55px
grid-template-areas: |
"sidebar header header header ."
"sidebar info info info ."
"sidebar left middle right ."
"sidebar left2 middle2 right2 ."
"servers servers people internet ."
mediaquery:
'(max-width: 650px)':
grid-template-columns: auto
grid-template-rows: 100%
grid-template-areas: |
"sidebar"
"header"
"info"
"people"
"middle"
"left"
"right"
"left2"
"middle2"
"right2"
"servers"
"internet"
'(max-width: 2600px)':
grid-gap: 5px
grid-template-columns: 100px repeat(3, 1fr) 0fr
grid-template-rows: 40px repeat(3, min-content) 55px auto
grid-template-areas: |
"sidebar header header header ."
"sidebar info info info ."
"sidebar left middle right ."
"sidebar left2 middle2 right2 ."
". servers people internet ."
". . . . ."
cards:
- type: custom:decluttering-card ### Sidebar ###
template: sidebar_template
view_layout:
grid-area: sidebar
- type: custom:decluttering-card ### Header ###
template: header_template
view_layout:
grid-area: header
- type: custom:decluttering-card ### Info ###
template: info_template
view_layout:
grid-area: info
- type: vertical-stack
cards:
- type: custom:room-card
title: Kitchen
rows:
- entities:
- entity: light.kitchen
name: Kitchen Lights
tap_action:
action: toggle
- entity: switch.signify_netherlands_b_v_lom009_switch
show_icon: true
name: Pixel Tablet
state_color: true
icon: mdi:tablet
tap_action:
action: toggle
- entities:
- entity: sensor.kitchen_illuminance
show_name: true
name: Lux
show_state: true
- entity: sensor.kitchen_temperature
show_name: true
name: Temperature
show_state: true
- entity: sensor.kitchen_humidity
show_name: true
name: Humidity
show_state: true
info_entities:
- entity: binary_sensor.kitchen_presence_group
show_icon: true
hide_if:
conditions:
- condition: equals
entity: binary_sensor.kitchen_presence_group
value: 'off'
- entity: binary_sensor.kitchen_door_sensor_open
show_icon: true
icon:
state_on: mdi:door-open
state_off: mdi:door-closed
cards:
- type: climate-card
entity: climate.kitchen_radiator
show_states:
- heat
name: Radiator
title: Kitchen
control:
_headings: true
_icons: true
_names: true
hvac:
heat:
icon: mdi:fire
name: 'On'
'off':
icon: mdi:power
name: 'Off'
- type: picture-entity
hide_unavailable: true
show_state: false
show_name: false
camera_view: auto
camera_image: camera.camera_hub_g3_e60b
entity: camera.camera_hub_g3_e60b
layout:
step: row
control: true
header: false
hide_if:
conditions:
- condition: not
value: idle
- type: custom:room-card
title: Lean-To
rows: null
info_entities:
- entity: binary_sensor.lean_to_camera_motion_detected
show_icon: true
hide_if:
conditions:
- condition: equals
entity: binary_sensor.lean_to_camera_motion_detected
value: 'off'
cards:
- type: picture-entity
hide_unavailable: true
show_state: false
show_name: false
camera_view: auto
camera_image: camera.lean_to_camera
entity: camera.lean_to_camera
layout:
step: row
control: true
header: false
hide_if:
conditions:
- condition: not
value: idle
view_layout:
grid-area: left2
- type: vertical-stack
cards:
- type: custom:room-card
title: Bedroom
rows:
- entities:
- entity: light.bedroom
name: Bedroom Lights
tap_action:
action: toggle
- entities:
- entity: sensor.bedroom_illuminance
show_name: true
name: Lux
show_state: true
- entity: sensor.bedroom_temperature
show_name: true
name: Temperature
show_state: true
- entity: sensor.bedroom_humidity
show_name: true
name: Humidity
show_state: true
info_entities:
- entity: binary_sensor.bedroom_presence_group
show_icon: true
hide_if:
conditions:
- condition: equals
entity: binary_sensor.bedroom_presence_group
value: 'off'
cards:
- type: climate-card
entity: climate.bedroom_radiator
show_states:
- heat
name: Radiator
title: Bedroom
control:
_headings: true
_icons: true
_names: true
hvac:
heat:
icon: mdi:fire
name: 'On'
'off':
icon: mdi:power
name: 'Off'
view_layout:
grid-area: middle
- type: vertical-stack
cards:
- type: custom:room-card
title: Hallway
rows:
- entities:
- entity: light.hallway
name: Hallway Lights
tap_action:
action: toggle
- entity: switch.ts011f_hallway_switch_left
show_icon: true
name: Yale Module
state_color: true
tap_action:
action: more-info
info_entities:
- entity: binary_sensor.ewelink_ms01_hallway_motion
show_icon: true
hide_if:
conditions:
- condition: equals
entity: binary_sensor.ewelink_ms01_hallway_motion
value: 'off'
- entity: binary_sensor.front_door_open
show_icon: true
icon:
state_on: mdi:door-open
state_off: mdi:door-closed
cards:
- type: climate-card
entity: climate.smart_thermostat
show_states:
- heat
name: Thermostat
title: Hallway
control:
_headings: true
_icons: true
_names: true
hvac:
heat:
icon: mdi:fire
name: 'On'
'off':
icon: mdi:power
name: 'Off'
- type: picture-entity
hide_unavailable: true
show_state: false
show_name: false
camera_view: auto
camera_image: camera.doorbell
entity: camera.doorbell
layout:
step: row
control: true
header: false
hide_if:
conditions:
- condition: not
value: idle
view_layout:
grid-area: middle2
- type: vertical-stack
cards:
- type: custom:room-card
title: Office
rows:
- entities:
- entity: light.office
name: Office Lights
tap_action:
action: toggle
- entity: cover.office_curtains
show_icon: true
name: Curtains
state_color: true
icon: mdi:curtains
tap_action:
action: toggle
- entities:
- entity: sensor.office_temperature
show_name: true
name: Temperature
show_state: true
- entity: sensor.office_humidity
show_name: true
name: Humidity
show_state: true
info_entities:
- entity: binary_sensor.office_presence_group
show_icon: true
state_color: true
hide_if:
conditions:
- condition: equals
entity: binary_sensor.office_presence_group
value: 'off'
cards:
- type: climate-card
entity: climate.office_radiator
show_states:
- heat
name: Radiator
title: Office
control:
_headings: true
_icons: true
_names: true
hvac:
heat:
icon: mdi:fire
name: 'On'
'off':
icon: mdi:power
name: 'Off'
view_layout:
grid-area: right2
- type: vertical-stack
cards:
- type: custom:room-card
title: Living Room
rows:
- entities:
- entity: light.living_room
name: Living Room Lights
tap_action:
action: navigate
path: living_room
- entity: cover.ts0601_living_room_blinds
show_icon: true
name: Blinds
state_color: true
icon: mdi:blinds-vertical
tap_action:
action: toggle
info_entities:
- entity: sensor.living_room_illuminance
show_name: true
name: Lux
show_state: true
- entity: sensor.living_room_temperature
show_name: true
name: Temperature
show_state: true
- entity: sensor.living_room_humidity
show_name: true
name: Humidity
show_state: true
- entity: binary_sensor.living_room_presence_group
show_icon: true
hide_if:
conditions:
- condition: equals
entity: binary_sensor.living_room_presence_group
value: 'off'
cards:
- type: climate-card
entity: climate.living_room_radiator
show_states:
- heat
name: Radiator
title: Living Room
control:
_icons: true
_headings: true
_names: true
hvac:
heat:
icon: mdi:fire
name: 'On'
'off':
icon: mdi:power
name: 'Off'
view_layout:
grid-area: left
- type: vertical-stack
cards:
- type: custom:room-card
title: Bathroom
rows:
- entities:
- entity: light.bathroom_lights
name: Bathroom Lights
tap_action:
action: toggle
- entities:
- entity: sensor.lumi_lumi_motion_ac02_illuminance
show_name: true
name: Lux
show_state: true
- entity: sensor.bathroom_temperature
show_name: true
name: Temperature
show_state: true
- entity: sensor.bathroom_humidity
show_name: true
name: Humidity
show_state: true
info_entities:
- entity: binary_sensor.lumi_lumi_motion_ac02_motion
show_icon: true
hide_if:
conditions:
- condition: equals
entity: binary_sensor.lumi_lumi_motion_ac02_motion
value: 'off'
cards:
- type: climate-card
entity: climate.bathroom_radiator
show_states:
- heat
name: Radiator
title: bathroom
control:
_headings: true
_icons: true
_names: true
hvac:
heat:
icon: mdi:fire
name: 'On'
'off':
icon: mdi:power
name: 'Off'
view_layout:
grid-area: right
- type: custom:decluttering-card ### Footer Server ###
template: server_footer_template
view_layout:
grid-area: servers
- type: custom:decluttering-card ### Footer People ###
template: people_footer_template
view_layout:
grid-area: people
- type: custom:decluttering-card ### Footer Internet ###
template: internet_footer_template
view_layout:
grid-area: internet
petro
(Petro)
August 9, 2023, 10:53am
9
no,
layout: &my_layout
... contents ...
and using it
layout: *my_layout
petro:
*my_layout
Thanks @petro this is exactly what i was after. It would be great if this worked in the same way as the decluttering cards so you could use the layout across different yaml files for each view within a dashboard but it still saves a lot of time!