# Template

**Clones a `<template>` part and fills it with data that doesn't exist when the server renders the page.**

Use it for anything the client adds after hydration: async search results, previews of uploaded files, or the rows of a recurring field. The markup of the item stays in your Fluid template, so it is styled and translated like the rest of the component.

## Usage

Declare the `<template>` with [`ui:template`](/docs/viewhelpers/template.md) inside the component. It needs exactly one root element:

```html
<ui:combobox.list>
    <ui:template name="itemTemplate" context="combobox">
        <ui:combobox.item>
            <ui:combobox.itemText>
                <span {ui:ref(name: 'title')}></span>
            </ui:combobox.itemText>
        </ui:combobox.item>
    </ui:template>
</ui:combobox.list>
```

Then clone it from the component with its hydrator, fill it and insert it:

```typescript
import { Template } from 'fluid-primitives';

for (const { value, title } of cities) {
    const instance = new Template(combobox.hydrator, 'itemTemplate', { value });

    const titleEl = instance.query<HTMLElement>('title');
    if (titleEl) titleEl.textContent = title;

    listEl.appendChild(instance);
}
```

`instance` is a `DocumentFragment`, so it can be appended as it is. `instance.root` keeps pointing at the item after the insertion has emptied the fragment.

With `value` the clone represents one real item: `data-value` is set on it and on the parts inside it that exist once per item, and independent components inside it, such as a `Field` with an `Input`, are prepared. Call the `mountAll()` of each name in `instance.componentNames` after you insert the clone.

## Options

The options of a `Template`.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `value` | `string` | No | `-` | Makes the clone represent one real item: sets `data-value` on its root and on every part inside it that exists once per item, and prepares independent root components inside it, such as a `Field` with an `Input`, so `mountAll()` can mount them. Leave it out for a template without a per-item value. |
| `attributes` | `Record<string, boolean \| string>` | No | `-` | Data attributes to set next to `value`, on the same elements. A boolean toggles a bare `data-x` attribute, `{ disabled: true }` sets `data-disabled` and `false` removes it. A string sets `data-x="value"`. Only has an effect together with `value`. |

## API

Clones the content of a `<template>` part, which must have exactly one root element, and throws otherwise. It is a `DocumentFragment`, so you can append it directly: `root` stays a valid reference to the element after the fragment has been emptied by the insertion.

It works for any "clone a `<template>` and fill it with data that doesn't exist at server render time" case, such as async search results, file upload previews or the rows of a FieldArray.

```typescript
class Template extends DocumentFragment
```

### Constructor

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `hydrator` | `ComponentHydrator` | Yes | `-` | The hydrator of the component that owns the `<template>`. |
| `part` | `string` | Yes | `-` | The name of the `<template>` part. |
| `options` | `TemplateOptions` | No | `{}` | See `TemplateOptions`. |

### Properties

| Name | Type | Description |
| --- | --- | --- |
| `root` | `HTMLElement` | The one root element of the clone. |
| `componentNames` | `string[]` | The client names of the independent root components found inside the clone, empty without `options.value` or when there are none. Call their `mountAll()` after you insert the clone into the document. |

### Methods

#### query()

Finds the first element of `part` inside the clone.

```typescript
query<T extends Element = HTMLElement>(part: string): T | null
```

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `part` | `string` | Yes | `-` |  |

#### queryAll()

Finds every element of `part` inside the clone.

```typescript
queryAll<T extends Element = HTMLElement>(part: string): T[]
```

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `part` | `string` | Yes | `-` |  |
