createRender
createRender lets you define complex Svelte component behaviors within the script.
It combines a component with its props to create a ComponentRenderConfig that is passed into Render#of to dynamically render Svelte components.
createRender accepts a Svelte component and either:
- an object of static props; or
- a getter returning the props, for dynamic props.
Event handlers are ordinary props: pass them as on<event> (for example onclick), the same way you would on any Svelte 5 component.
Usage
createRender: (component: Component, props?: Props) => ComponentRenderConfig
Creates a render configuration with a Svelte component and static props.
<script>
import Profile from './Profile.svelte'
const profile = createRender(Profile, {
name: 'Alan Turing'
})
</script>
<Render of={profile} /><script>
import Profile from './Profile.svelte'
const profile = createRender(Profile, {
name: 'Alan Turing'
})
</script>
<Render of={profile} />Props may themselves be reactive objects. The plugin state boxes are the common case: pass the box, and let the component read and write its current.
cell: ({ row }, { pluginStates }) => {
const { isSelected, isSomeSubRowsSelected } = pluginStates.select.getRowState(row)
return createRender(SelectIndicator, { isSelected, isSomeSubRowsSelected })
}cell: ({ row }, { pluginStates }) => {
const { isSelected, isSomeSubRowsSelected } = pluginStates.select.getRowState(row)
return createRender(SelectIndicator, { isSelected, isSomeSubRowsSelected })
}<!-- SelectIndicator.svelte -->
<script lang="ts">
import type { Box, ReadonlyBox } from '@humanspeak/svelte-headless-table'
const { isSelected, isSomeSubRowsSelected }: {
isSelected: Box<boolean>
isSomeSubRowsSelected: ReadonlyBox<boolean>
} = $props()
</script>
<input
type="checkbox"
checked={isSelected.current}
indeterminate={isSomeSubRowsSelected.current}
onchange={(e) => (isSelected.current = e.currentTarget.checked)}
/><!-- SelectIndicator.svelte -->
<script lang="ts">
import type { Box, ReadonlyBox } from '@humanspeak/svelte-headless-table'
const { isSelected, isSomeSubRowsSelected }: {
isSelected: Box<boolean>
isSomeSubRowsSelected: ReadonlyBox<boolean>
} = $props()
</script>
<input
type="checkbox"
checked={isSelected.current}
indeterminate={isSomeSubRowsSelected.current}
onchange={(e) => (isSelected.current = e.currentTarget.checked)}
/>createRender: (component: Component, props?: () => Props) => ComponentRenderConfig
Creates a render configuration with a Svelte component and dynamic props. <Render> calls the getter inside its template, so the component re-renders with new props when the rune state the getter reads changes.
<script>
import Profile from './Profile.svelte'
let name = $state('Grace Hopper')
const profile = createRender(Profile, () => ({ name }))
</script>
<input bind:value={name} />
<Render of={profile} /><script>
import Profile from './Profile.svelte'
let name = $state('Grace Hopper')
const profile = createRender(Profile, () => ({ name }))
</script>
<input bind:value={name} />
<Render of={profile} />Event handlers
Pass handlers as on<event> props:
<script>
import Notice from './Notice.svelte'
let count = $state(0)
const notice = createRender(Notice, () => ({
count,
onclick: () => count++
}))
</script>
<Render of={notice} /><script>
import Notice from './Notice.svelte'
let count = $state(0)
const notice = createRender(Notice, () => ({
count,
onclick: () => count++
}))
</script>
<Render of={notice} />ComponentRenderConfig#on() and eventHandlers. Replace .on('click', handler) with an onclick prop.createSnippetRender: (snippet: Snippet<[Args]>, args?: Args | (() => Args)) => SnippetRenderConfig
Creates a render configuration from a Svelte 5 snippet instead of a component. The snippet receives a single argument, either a static value or a getter returning it (the snippet re-renders when the rune state the getter reads changes). Omit args for snippets that take no argument.
args is always called as a getter. To pass a function as the snippet's argument, wrap it: createSnippetRender(snippet, () => fn).This works from <script> because Svelte hoists top-level snippets, so a snippet declared in the component’s markup can be referenced while defining columns.
<script>
import { createSnippetRender } from '@humanspeak/svelte-headless-table'
const columns = table.createColumns([
table.column({
accessor: 'name',
header: 'Name',
cell: ({ value }) => createSnippetRender(nameCell, value)
})
])
</script>
{#snippet nameCell(name)}
<strong>{name}</strong>
{/snippet}<script>
import { createSnippetRender } from '@humanspeak/svelte-headless-table'
const columns = table.createColumns([
table.column({
accessor: 'name',
header: 'Name',
cell: ({ value }) => createSnippetRender(nameCell, value)
})
])
</script>
{#snippet nameCell(name)}
<strong>{name}</strong>
{/snippet}