# ComponentHydrator

**Finds the parts of one component instance in the DOM.**

A component without a state machine finds its parts with a `ComponentHydrator`. The server marks the parts with [`ui:ref`](/docs/core-concepts/hydration.md#content-marking-elements-for-hydration), the hydrator queries them by name.

## Usage

The `mountAll` callback hands you `createHydrator`, which returns a hydrator scoped to the current instance:

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

mountAll('ui:productGallery', ({ createHydrator }) => {
    const hydrator = createHydrator();

    const thumbnails = hydrator.queryAll<HTMLButtonElement>('thumbnail');
    const image = hydrator.query<HTMLImageElement>('image');
    if (!image) return;

    thumbnails.forEach(thumbnail => {
        thumbnail.addEventListener('click', () => {
            image.src = thumbnail.dataset.src ?? image.src;
        });
    });
});
```

`query()` returns the first matching element or `null`, `queryAll()` every match. Both search the whole document, so content that was portaled elsewhere is found too. Pass an element as the second argument to narrow the search to it.

Every `Component` instance exposes its own hydrator as `instance.hydrator`, for example `combobox.hydrator.query('list')`. Mark an element you create on the client like `ui:ref` does with `hydrator.stamp(el, 'part', value?)`.

Outside a `mountAll` callback, create a hydrator with the component name and the root id. It takes the bare component name, without a namespace:

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

const hydrator = new ComponentHydrator('productGallery', 'root-id-123');
```

## ComponentHydrator

Finds the parts of one component instance. Every part that `ui:ref` renders carries a `data-<component>-<part>="<rootId>"` attribute, so a lookup needs no id and searches the whole document by default. That is also what finds content that was portaled away from the root.

```typescript
class ComponentHydrator
```

### Constructor

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `componentName` | `string` | Yes | `-` | The name of the component, in camelCase. |
| `rootId` | `string \| undefined` | Yes | `-` | The `rootId` the component was rendered with. Throws if it is missing. |
| `doc` | `Document` | No | `document` | The document the parts are searched in. |

### Properties

| Name | Type | Description |
| --- | --- | --- |
| `componentName` | `string` | The name of the component, in camelCase. |
| `clientComponentName` | `string` | The kebab-case form of `componentName`, as it appears in attribute names. |
| `doc` | `Document` | The document the parts are searched in. |
| `rootId` | `string` | The `rootId` the component was rendered with. |

### Methods

#### attr()

The name of the attribute that marks `part`, e.g. `data-accordion-item-trigger`.

```typescript
attr(part: string): string
```

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

#### selector()

The CSS selector of every element of `part` that belongs to this instance.

```typescript
selector(part: string): string
```

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

#### scopeKey()

The key that identifies `part`, and optionally one `value` of it, across this instance.

```typescript
scopeKey(part: string, value?: string): string
```

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

#### query()

Finds the first element of `part`.

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

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `part` | `string` | Yes | `-` | The name of the part, in camelCase. |
| `parent` | `Element \| Document` | No | `this.doc` | Where to search, the whole document by default. |

**Returns** `T | null`. The element, or `null` if there is none.

#### queryAll()

Finds every element of `part`.

```typescript
queryAll<T extends Element = HTMLElement>(part: string, parent?: Element | Document): T[]
```

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `part` | `string` | Yes | `-` | The name of the part, in camelCase. |
| `parent` | `Element \| Document` | No | `this.doc` | Where to search, the whole document by default. |

#### stamp()

Marks an element as `part` of this instance, like `ui:ref` does on the server. For elements you create after hydration.

```typescript
stamp(element: Element, part: string, value?: string): void
```

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `element` | `Element` | Yes | `-` | The element to mark. |
| `part` | `string` | Yes | `-` | The name of the part, in camelCase. |
| `value` | `string` | No | `-` | Sets `data-value`, for a part that exists once per item. |

#### destroy()

Nothing to release yet, it exists so every instance can be destroyed alike.

```typescript
destroy(): void
```
