> For AI agents: the complete documentation index is available at https://gultyayev.github.io/ngx-virtual-dnd/llms.txt, the full documentation bundle is available at https://gultyayev.github.io/ngx-virtual-dnd/llms-full.txt.

# Directives

## DraggableDirective

**Selector:** `[vdndDraggable]`

Makes an element draggable with mouse, touch and keyboard. See [Drag behavior](https://gultyayev.github.io/ngx-virtual-dnd/guide/features/drag-behavior.md).

| Input                | Type                 | Default      | Description                                                                                |
| -------------------- | -------------------- | ------------ | ------------------------------------------------------------------------------------------ |
| `vdndDraggable`      | `string`             | **required** | Unique ID across all lists; must equal the list's item ID                                  |
| `vdndDraggableGroup` | `string`             | —            | Group name. Required unless a `vdndGroup` is in scope where the template is declared       |
| `vdndDraggableData`  | `unknown`            | —            | Arbitrary data, delivered in drag events, `DropEvent.source.data` and the preview template |
| `disabled`           | `boolean`            | `false`      | Prevent dragging                                                                           |
| `dragHandle`         | `string`             | —            | CSS selector; only presses inside a match within the item start a drag                     |
| `dragThreshold`      | `number`             | `5`          | Distance in px before a drag starts                                                        |
| `dragDelay`          | `number`             | `0`          | Hold time in ms before a drag can start                                                    |
| `lockAxis`           | `'x' \| 'y' \| null` | `null`       | Axis to freeze: `'x'` moves vertically only, `'y'` horizontally only                       |

| Output      | Type             | Description                                           |
| ----------- | ---------------- | ----------------------------------------------------- |
| `dragStart` | `DragStartEvent` | A drag started                                        |
| `dragEnd`   | `DragEndEvent`   | A drag ended, dropped or not (see `destinationIndex`) |

## DroppableDirective

**Selector:** `[vdndDroppable]`

Marks an element as a drop target.

| Input                  | Type                        | Default      | Description                                                                                      |
| ---------------------- | --------------------------- | ------------ | ------------------------------------------------------------------------------------------------ |
| `vdndDroppable`        | `string`                    | **required** | Unique ID on the page                                                                            |
| `vdndDroppableGroup`   | `string`                    | —            | Group name. Required unless inherited from a `vdndGroup` ancestor                                |
| `vdndDroppableData`    | `unknown`                   | —            | Arbitrary data, delivered as `DropEvent.destination.data`                                        |
| `disabled`             | `boolean`                   | `false`      | Skip this target for pointer and keyboard; releasing over it emits no `drop`                     |
| `autoScrollEnabled`    | `boolean`                   | `true`       | Scroll when dragging near the edges                                                              |
| `autoScrollConfig`     | `Partial<AutoScrollConfig>` | `{}`         | Auto-scroll tuning                                                                               |
| `constrainToContainer` | `boolean`                   | `false`      | Keep the preview and drop position inside the nearest `vdndScrollable` ancestor, or this element |

| Output            | Type                   | Description                                                                          |
| ----------------- | ---------------------- | ------------------------------------------------------------------------------------ |
| `drop`            | `DropEvent`            | An item was dropped here (destination only; at release, right after `dragEnd`)       |
| `placeholderMove` | `PlaceholderMoveEvent` | The placeholder moved within this droppable (every row displacement). Added in 3.2.0 |

## DroppableGroupDirective

**Selector:** `[vdndGroup]`

Provides a group name to every draggable and droppable inside it. Declare item templates inside this element as well.

| Input       | Type     | Default      | Description |
| ----------- | -------- | ------------ | ----------- |
| `vdndGroup` | `string` | **required** | Group name  |

## ScrollableDirective

**Selector:** `[vdndScrollable]`

Marks the element that scrolls for `<vdnd-virtual-content>` or `*vdndVirtualFor`. The element needs `overflow: auto` (or `scroll`) and a height. Adds the `vdnd-scrollable` class and `overflow-anchor: none`, and `data-scroll-inset-top` / `data-scroll-inset-bottom` while `scrollInsetTop` / `scrollInsetBottom` are not 0. A `*vdndVirtualFor` used directly inside it sets `position: relative` on it when it is not positioned (see [VirtualForDirective](#virtualfordirective)).

| Input               | Type                        | Default | Description                                                              |
| ------------------- | --------------------------- | ------- | ------------------------------------------------------------------------ |
| `scrollContainerId` | `string`                    | —       | ID used to register for auto-scroll                                      |
| `autoScrollEnabled` | `boolean`                   | `true`  | Scroll when dragging near the edges                                      |
| `autoScrollConfig`  | `Partial<AutoScrollConfig>` | `{}`    | Auto-scroll tuning                                                       |
| `scrollInsetTop`    | `number`                    | `0`     | Height (px) of content pinned over the top edge, e.g. a sticky header    |
| `scrollInsetBottom` | `number`                    | `0`     | Height (px) of content pinned over the bottom edge, e.g. a sticky footer |

`scrollInsetTop` and `scrollInsetBottom` tell a drag which part of the element sticky content inside it covers. You measure the heights; the drag treats the element as the part between them: `constrainToContainer` keeps the preview there, the auto-scroll zones start at its edges (a pointer over the sticky content scrolls at full speed), a pointer over the sticky content is not over the lists in the element (nor in scroll containers nested in it), and a keyboard drag keeps the placeholder clear of it. See [Sticky headers and footers](https://gultyayev.github.io/ngx-virtual-dnd/guide/features/page-scroll.md#sticky-headers-and-footers).

## VirtualForDirective

**Selector:** `*vdndVirtualFor`

Structural directive that renders only the visible items. Use it inside `<vdnd-virtual-viewport>`, `<vdnd-virtual-content>` or a `vdndScrollable` element.

```angular-html
<ng-container
  *vdndVirtualFor="let task of tasks(); trackBy: trackById; itemHeight: 48; overscan: 3"
>
  <div [vdndDraggable]="task.id">{{ task.title }}</div>
</ng-container>
```

| Key                 | Type                                  | Default      | Description                                           |
| ------------------- | ------------------------------------- | ------------ | ----------------------------------------------------- |
| `of`                | `T[]`                                 | **required** | Items                                                 |
| `trackBy`           | `(index: number, item: T) => unknown` | **required** | Must return the same ID as the item's `vdndDraggable` |
| `itemHeight`        | `number`                              | inherited    | Required when not inside a viewport component         |
| `dynamicItemHeight` | `boolean`                             | inherited    | Measure rows                                          |
| `droppableId`       | `string`                              | inherited    | Taken from the enclosing `vdndDroppable`              |
| `overscan`          | `number`                              | `3`          | Extra rows rendered above and below                   |

Template context (`VirtualForContext<T>`): `$implicit`, `index`, `first`, `last`, `count`.

It always recycles rows: the view of a row that scrolls out renders a row that scrolls in. See [Row recycling](https://gultyayev.github.io/ngx-virtual-dnd/guide/features/performance.md#row-recycling).

Used directly in a `vdndScrollable` element (no viewport component), it positions each row absolutely at its offset and opens a gap for the drag placeholder by moving the rows after it down. The rows scroll with the element only if it is their containing block, so when neither the element nor an element between it and the rows is positioned, the directive sets `position: relative` on it.

```angular-html
<div vdndScrollable vdndDroppable="tasks" (drop)="onDrop($event)" style="overflow: auto; height: 400px">
  <ng-container *vdndVirtualFor="let task of tasks(); itemHeight: 48; trackBy: trackById">
    <div [vdndDraggable]="task.id">{{ task.title }}</div>
  </ng-container>
</div>
```

## ContentHeaderDirective

**Selector:** `[vdndContentHeader]`

Marks a header projected into `<vdnd-virtual-content>`. Its height is measured and used as the content offset. No inputs or outputs.
