# SharedDoc Class

## Content

[SharedDoc ](/spreadjs/api/v18/collaboration/js-collaboration-ot-client/classes/SharedDoc)represents a shared document instance, used to manage document snapshots (`snapshot`) and operations (`op`), synchronizing data with the server through a connection (`Connection`). It supports the Operational Transformation (OT) mechanism to ensure consistency of multi-user operations. This document explains how to use `SharedDoc` on the client side, including:

* Initialize `SharedDoc`
* Create or delete documents
* Request and update document snapshots
* Submit, receive, and transform operations
* Listen for events

## Initialization

[Initalizing SharedDoc](/spreadjs/docs/v18/spreadjs-collaboration-server/collaboration-framework/js-collaboration-ot/initalizing-shareddoc)

## Properties

| Property Name | Description | Types |
| ------------- | ----------- | ----- |
| `id` | Returns the unique identifier of the shared document. | `string` (read-only) |
| `version` | Indicates the version number of the current snapshot. | \`number \| \| |
| `type` | Indicates the operation type (Operational Transformation type) of the snapshot. | \`OT\_Type\<S\, T\> \| \| |
| `data` | Indicates the data of the current snapshot. | \`S \| \| |
| `connection` | Returns the connection object of the shared document. | `Connection` (read-only) |

## Methods

### fetch

Retrieve the document's snapshot data, with the result stored in `doc.data`.

```typescript
fetch(): Promise<void>
```

**Return**

* `Promise<void>`: Returns a promise that resolves after the snapshot is fetched, the fetched snapshot data is 'doc.data'.

**Example**

```typescript
try {
    await doc.fetch();
    if (!doc.type) {
        return console.log('Document does not exist');
    }
    console.log('Document snapshot', doc.data);
} catch (error) {
    if (error) {
        return console.error(error);
    }
}
```

### subscribe

Retrieve the document's snapshot data and listen for subsequent updates.

```typescript
subscribe(): Promise<void>
```

**Return**

* `Promise<void>`: Returns a promise that resolves after the snapshot is subscribed, the subscribed snapshot data is 'doc.data'.

**Example**

```typescript
try {
    await doc.subscribe();
    if (!doc.type) {
        return console.log('Document does not exist');
    }
    console.log('Document snapshot', doc.data);
    
    doc.on('op', (op, source) => {
        console.log('Document updated', op, source);
    });
} catch (error) {
    if (error) {
        return console.error(error);
    }
}
```

### submitOp

Submit an operation to the document.

```typescript
submitOp(component: T, options?: IOptions): Promise<void>
```

**Parameters**

* `component` (`T`): The op component.
* `options` (`IOptions`): Options for the operation (optional).

**Return**

* `Promise<void> `: Returns a promise that resolves after the op is submitted.

**Example**

```typescript
// Insert text 'x' at position 1
await doc.submitOp({ pos: 1, text: 'Hi' }, { source: doc.connection.id });
console.log('Operation submitted');
```

### create

Create a new document.

```typescript
create(data: S, type: string, options: IOptions): Promise<void>
```

**Parameters**

* `data` (`S`): The data used to initialize the snapshot.
* `type` (`string`): The URI of the OT type.
* `options` (`IOptions`): Options for the operation.

**Return**

* `Promise<void>`: Returns a promise that resolves after the document is created.

**Example**

```typescript
try {
    await doc.create('Hello', textType.uri, {});
    console.log('Document created successfully:', doc.data); // "Hello"
} catch (err) {
    console.error('Creation failed:', err);
}
```

### fetchHistorySnapshot

Retrieve historical snapshot data of the document.

```typescript
fetchHistorySnapshot(options: IHistorySnapshotRequestOptions): Promise<ISnapshot<S>>
```

**Parameter**

* `options` (`IHistorySnapshotRequestOptions`): Historical snapshot request options.

**Return**

* `Promise<ISnapshot<S>>`: Returns a promise that resolves after the history snapshot is fetched.

**Example**

```typescript
const snapshot = await doc.fetchHistorySnapshot({ version: 6 }, textType.uri, {});
console.log('Document created successfully, snapshot :', snapshot);
```

### del

Delete the document.

```typescript
del(options: IOptions): Promise<void>
```

**Parameter**

* `options` (`IOptions`): Deletion options.

**Return**

* `Promise<void>`: Returns a promise that resolves after the document is deleted.

### hardRollback

Forcefully rollback the snapshot data to the latest version.

```typescript
hardRollback(): Promise<void>
```

**Return**

* `Promise<void>`: Returns a promise that resolves when the rollback is complete.

### destroy

Destroy the instance and release all resources.

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

## Events

`SharedDoc` supports the following events, managed by the `on`, `once`, and `off` methods:

| Event Name | Description | Parameters |
| ---------- | ----------- | ---------- |
| `error` | Triggered when an error occurs. | `err`: `OTError` object |
| `load` | Triggered after retrieving or subscribing to a snapshot. | None |
| `create` | Triggered when the document is created. | `source`: Operation source |
| `beforeOp` | Triggered before an operation is applied. | `op`: Operation data, `source`: Source |
| `op` | Triggered after an operation is applied. | `op`: Operation data, `source`: Source |
| `del` | Triggered when the document is deleted. | `data`: Data before deletion, `source`: Source |
| `hardRollback` | Triggered during a forced rollback. | None |

### on

Register an event listener.

```typescript
on<NAME extends keyof ISharedDocEvents<S, T>>(name: NAME, f: ISharedDocEvents<S, T>[NAME]): ISharedDocEvents<S, T>[NAME];
```

**Parameters**

* `name` (`NAME`): Event name, must be a key in the `ISharedDocEvents<S, T>` interface.
* `f` (`ISharedDocEvents<S, T>[NAME]`): Event handler function.

**Return**

* `ISharedDocEvents<S, T>[NAME]`: The registered event handler.

**Example**

```typescript
doc.on('op', (op, source) => {
    if (source !== doc.connection.id) {
        console.log('receive op from server:', op);
    }
});
```

### once

Register an event listener that triggers only once.

```typescript
once<NAME extends keyof ISharedDocEvents<S, T>>(name: NAME, f: ISharedDocEvents<S, T>[NAME]): void;
```

**Parameters**

* `name` (`NAME`): Event name.
* `f` (`ISharedDocEvents<S, T>[NAME]`): Event handler function.

**Example**

```typescript
doc.once('op', (op, source) => {
    console.log('op', op, source);
});
```

### off

Remove a specific event listener.

```plaintext
off<NAME extends keyof ISharedDocEvents<S, T>>(name: NAME, f: ISharedDocEvents<S, T>[NAME]): void;
```

**Parameters**

* `name` (`NAME`): Event name.
* `f` (`ISharedDocEvents<S, T>[NAME]`): Event handler function to remove.

## Integration with UI Components

The following figure shows a collaborative process.
![sharedoc_class](https://cdn.mescius.io/document-site-files/images/7719ad0a-f083-46d7-aff6-f63e2e187c15/sharedoc_class.6c68f4.png)

```typescript
// Initialize the UI component. xxx.uiComponent is fictional and should be replaced with an actual UI component implementation, such as Quill or others.
const uiComponent = new xxx.uiComponent();

// Subscribe to the document
doc.subscribe().then(async () => {
    // Create the document if it does not exist
    if (!doc.type) {
        try {
            await doc.create('Hello', textType.uri, {});
            console.log('Created successfully:', doc.data);
        } catch (error) {
            console.error('Creation failed:', error);
            return;
        }
    }

    uiComponent.setText(doc.data);

    // Listen for operations
    doc.on('op', (op, source) => {
        if (source === doc.connection.id) {
            return;
        }
        console.log('Received operation:', op, 'Current data:', doc.data);

        uiComponent.applyOp(op.pos, op.text); // Prefer incremental updates
        // Or uiComponent.setText(doc.data); // Full update
    });

    // Listen for UI component operations and submit to the server
    uiComponent.on('op', (op) => {
        await doc.submitOp(op, { source: doc.connection.id });
    });
})
```

Try to build a real-time collaborative text editor: [Tutorial: Real-Time Collaborative Text Editor](/spreadjs/docs/v18/spreadjs-collaboration-server/collaboration-framework/js-collaboration-ot/tutorial-real-time-collaborative-text-editor).