Skip to main content

Template

The Template component mirrors the nunjucks template by using named slots instead of blocks and props instead of variables

<script>
  import { Template } from '@danboscaro/govuk-svelte'
</script>

<Template containerClasses=".some-class">
  <svelte:fragment slot="pageTitle">
    <title>Hello title</title>
  </svelte:fragment>

  <svelte:fragment slot="content">
    <h1 class="govuk-heading-xl">Hello content</h1>
  </svelte:fragment>
</Template>

By using the template as a component, svelte only has access to a root element within the body tag, so some extra setup is required to complete the page

Note: the pageTitle block contains the title tag as it is not possible to add a slot inside that tag, this is the only difference in all of the nunjucks blocks

src/app.html

Add the "govuk-template" class to the html tag and the "govuk-template__body" class to the body tag

<!DOCTYPE html>
<html lang="en" class="govuk-template">
  ...
  <body class="govuk-template__body">
    ...
  </body>
</html>

This also applies if you require any of the following nunjucks options; bodyAttributes, bodyClasses, htmlClasses or htmlLang, which can be set statically in the src/app.html file or these can be set dynamically with a server hook that substitutes them

Substitute unavailable options

Add a placeholder for the variable you want to substitute in the src/app.html

<!DOCTYPE html>
<html lang="%htmlLang%" class="govuk-template">
  ...
</html>

Then create a src/hooks.server.js file with the following handle function that substitutes the placeholder

/** @type {import('@sveltejs/kit').Handle} */
export function handle({ event, resolve }) {
  return resolve(event, {
    transformPageChunk: ({ html }) => html.replace('%htmlLang%', 'cy')
  });
}

Using the Template component in a +layout.svelte file

There is a limitation when using the Template component in a layout file. Currently svelte layout files do not support named slots, so if you setup a template within a layout file there is only a single slot that can be forwarded to pages that use that layout

This may be addressed in the future see this github comment from a SvelteKit maintainer for more details on this

If you don't require multiple slots from the template to be overridden in you pages then this probably wont be an issue for you, but some things can be updated per page from the suggestions in the comment, for example, to use the Template in a layout and also update the page title per page:

src/+page.svelte

<h1 class="govuk-heading-l">New page heading</h1>

src/+page.server.js

export async function load() {
  return {
    title: 'New page title' // <-- set the title for the page in the data object available to the layout
  };
}

src/+layout.svelte

<script>
  import { Template } from '@danboscaro/govuk-svelte'
  import { page } from '$app/stores';
</script>

<Template>
  <svelte:fragment slot="pageTitle">
    <title>{$page.data.title}</title>
  </svelte:fragment>

  <svelte:fragment slot="content">
    <slot></slot> <-- this is where the +page.svelte content will be placed
  </svelte:fragment>
</Template>