# TableGridSwitchDragAndDrop

**Category:** Features/Sort/Drag and Drop

## Design

### Description

Enables [drag and drop](./?path=/story/features-sort-drag-and-drop--overview) functionality on a [`TableGridSwitch`](./?path=/story/base-components-collections-grid-grid--grid) component.

#### Usage

1. Define a [`TableGridSwitch`](./?path=/story/base-components-collections-tablegridswitch-tablegridswitch--tablegridswitch) component.
1. Import and pass the `TableGridSwitchDragAndDrop` to the `dragAndDrop` prop on the `TableGridSwitch`.
1. Define the relevant drag and drop props on the [`TableGridSwitch`](./?path=/story/base-components-collections-tablegridswitch-tablegridswitch--tablegridswitch&tab=API):

      * `dragAndDropSubmit`
      * `dragAndDropCancel` (optional)
      * `dragAndDropBulkSubmit` (optional)
      * `dragAndDropCategories` (optional)
      * `dragAndDropReorderModeToolbar` (optional)


```tsx
import { TableGridSwitchDragAndDrop } from '@wix/patterns';
```

### TableGridSwitch

Drag and drop items in both a table view and a grid view.

```tsx
import { Avatar, Text } from '@wix/design-system';
import React from 'react';
import { Delete } from '@wix/wix-ui-icons-common';
import { CollectionPage } from '@wix/patterns/page';
import {
  TableGridSwitch,
  TableGridSwitchDragAndDrop,
  useTableGridSwitchCollection,
  useOptimisticActions,
  CursorQuery,
} from '@wix/patterns';
import { tasks } from '@wix/crm';

function TableGridSwitchExample() {
  const { queryTasks, moveTaskAfter, deleteTask, countTasks } = tasks;

  const state = useTableGridSwitchCollection<tasks.Task>({
    queryName: 'tasks-TableGridSwitch',
    paginationMode: 'cursor',
    fetchData: async (query: CursorQuery) => {
      const { limit, cursor } = query;

      let queryBuilder = queryTasks().limit(limit);

      if (cursor) {
        queryBuilder = queryBuilder.skipTo(cursor);
      }

      return queryBuilder.find().then((res) => {
        const { items = [], cursors } = res;
        return {
          items,
          cursor: cursors.next,
        };
      });
    },
    fetchTotal: async (_query: CursorQuery) => {
      const filter = {};
      return countTasks({ filter }).then((res) => res.count as number);
    },
    itemKey: (item) => item._id as string,
    itemName: (item) => item.title as string,
    fetchErrorMessage: () => 'Error fetching tasks',
  });

  const optimisticActions = useOptimisticActions(state.collection);

  const _deleteTask = (task: tasks.Task) => {
    optimisticActions.deleteOne(task, {
      submit: async (tasks) =>
        await Promise.all(tasks.map((task) => deleteTask(task._id as string))),
    });
  };

  return (
    <CollectionPage height="400px">
      <CollectionPage.Header title={{ text: 'Tasks' }} />
      <CollectionPage.Content>
        <TableGridSwitch
          search={false}
          dragAndDrop={TableGridSwitchDragAndDrop}
          dragAndDropSubmit={(event) =>
            moveTaskAfter(event.from.item._id as string, {
              beforeTaskId: event.after
                ? (event.after.item._id as string)
                : null,
            })
          }
          state={state}
          columns={[
            {
              title: '',
              width: '50px',
              render: (task) => <Avatar name={task.title!} />,
            },
            {
              title: 'Title',
              width: '250px',
              render: (task) => task.title,
            },
            {
              title: 'Due Date',
              render: (task) => task.dueDate?.toLocaleString(),
            },
          ]}
          actionCell={(item, index, api) => {
            return {
              secondaryActions: [
                {
                  text: `Delete task`,
                  icon: <Delete />,
                  onClick: () => {
                    api.openConfirmDeleteModal({
                      content: (
                        <Text>
                          Are you sure want to delete &nbsp
                          <Text weight="bold">{item.title}</Text> task?
                        </Text>
                      ),
                      primaryButtonOnClick: () => _deleteTask(item),
                    });
                  },
                },
              ],
            };
          }}
        />
      </CollectionPage.Content>
    </CollectionPage>
  );
}
```

## BI

### Events

  Event   |   Description   |
--------- | --------------- |
[144:138](https://bo.wix.com/data-tools/bi-catalog-app/event/144:138) | Sent when a user clicks on an item and tries to drag it, in order to sort the items manually
[144:139](https://bo.wix.com/data-tools/bi-catalog-app/event/144:139) | Sent when a user finish to drag an item
[144:140](https://bo.wix.com/data-tools/bi-catalog-app/event/144:140) | Sent when a user finish to drag items but those changes weren't update in the server from different reasons
[144:141](https://bo.wix.com/data-tools/bi-catalog-app/event/144:141) | Sent when a user clicks on a "try again" CTA he gets in an error notification



### Component load events
Event   |   Description   |
--------- | --------------- |
[144:110](https://bo.wix.com/data-tools/bi-catalog-app/event/144:110) | Sent when a Wix Patterns component starts loading
[144:111](https://bo.wix.com/data-tools/bi-catalog-app/event/144:111) | Sent when a Wix Patterns component is done loading


#### 🐪 Couldn't find what you need?
* Check our [BI Catalog](https://bo.wix.com/data-tools/bi-catalog-app?viewId=all-items-view&selectedColumns=src%2Cevid%2Cname%2Cowner%2Cproduct%2CuserType+false%2CdateUpdated%2CdateCreated+false%2CcreatedBy+false%2Cstatus&source=%5B%7B%22id%22%3A%22144%22%2C%22name%22%3A%22144+-+Cairo%22%7D%5D)
* Contact us on [#cairo-bi](https://wix.slack.com/archives/C03N53KURH9)


