> ## Documentation Index
> Fetch the complete documentation index at: https://docs.talview.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Form

> Dynamic form loading and submission with the Proview SDK

## What is Form module

The Form module is part of the Proview SDK, exposed as `Proview.form`. It provides a complete solution for loading, rendering, and managing dynamic forms with integrated authentication.

Once initialized, it lets your application:

* **Load forms** — render forms dynamically by form ID.
* **Submit forms** — handle form submission and validation automatically.
* **Mount UI** — display forms in `sidepanel`, `popup`, or `inline` layout modes.
* **React to events** — subscribe to ready, submitted, and error events.

***

## Quickstart

### 1. Load the SDK

Ensure the Proview SDK script is loaded (see [Getting Started](/sdk/getting-started)).

```html theme={null}
<script
  src="https://sdk.tlv.cx"
  async
  crossorigin="anonymous"
></script>
```

### 2. Initialize credential

The SDK supports Firebase as a credentialing provider for authentication.

```javascript theme={null}
const firebaseCredential = Proview.auth.FirebaseAuthStrategy({
  token: 'your-firebase-auth-token',
});
```

### 3. Initialize form module

Initialize the form module with the Firebase credential.

```javascript theme={null}
const form = Proview.form.init({
  dsn: 'project-dsn',
  projectId: 'project-123',
  credential: firebaseCredential,
});
```

### 4. Access user object

Once initialized, the user object becomes available globally at `Proview.user` and is Firebase-compatible with `getIdToken()` method.

```javascript theme={null}
const user = Proview.user;
console.log(user.uid, user.email, user.displayName);

// Get ID token when needed
const idToken = await user.getIdToken();
```

### 5. Mount UI

Mount the form UI into a container element.

```javascript theme={null}
const mounted = form.mount({
  formId: 'form-123',
  containerId: 'form-container',
  mountMode: {
    mode: 'sidepanel', // or 'popup' or 'inline'
  },
});
```

### 6. Open form

Open the form to load data and display the UI.

```javascript theme={null}
const formInstance = await form.open();
```

### 7. Subscribe to events

Listen to form lifecycle events.

```javascript theme={null}
formInstance
  .on('ready', () => {
    console.log('Form is ready for user input');
  })
  .on('submitted', () => {
    console.log('Form submitted successfully');
  })
  .on('error', ({ message }) => {
    console.error('Form error:', message);
  });
```

### 8. Teardown

When done, unmount the UI.

```javascript theme={null}
mounted.unmount();
```

***

## API Reference

### `Proview.form.init(options)`

Creates a form module instance with integrated authentication.

**Input**

```javascript theme={null}
type FormInitOptions = {
  dsn: string;               // Required: Project DSN
  projectId: string;         // Required: Project ID
  credential: Credential;    // Required: Authentication credential (e.g., FirebaseAuthStrategy)
};
```

**Returns** — `FormModule`

```javascript theme={null}
type FormModule = {
  mount(options: MountOptions): MountedFormUi;
  open(): Promise<FormInstance>;
};
```

The authenticated user is available globally at `Proview.user` after initialization.

***

### `form.mount(options)`

Mounts the form UI into a container element.

|             |                 |
| ----------- | --------------- |
| **Input**   | `MountOptions`  |
| **Returns** | `MountedFormUi` |

**MountOptions**

```javascript theme={null}
type MountOptions = {
  formId: string;                // Required: Form ID to load
  containerId: string;           // Required: DOM element ID
  mountMode: {
    mode: 'sidepanel' | 'popup' | 'inline';  // Required: Layout mode
  };
};
```

**MountedFormUi**

```javascript theme={null}
type MountedFormUi = {
  unmount(): void;  // Removes UI from DOM
};
```

**Example:**

```javascript theme={null}
const firebaseCredential = Proview.auth.FirebaseAuthStrategy({
  token: 'your-firebase-auth-token',
});

const form = Proview.form.init({
  dsn: 'project-dsn',
  projectId: 'project-123',
  credential: firebaseCredential,
});

const mounted = form.mount({
  formId: 'form-123',
  containerId: 'form-container',
  mountMode: {
    mode: 'popup',
  },
});

// Later, when done
mounted.unmount();
```

***

### `form.open()`

Loads form data and displays the form UI. Uses the formId specified in mount().

|             |                         |
| ----------- | ----------------------- |
| **Input**   | None                    |
| **Promise** | `Promise<FormInstance>` |
| **Async**   | Yes, requires await     |

**FormInstance**

```javascript theme={null}
type FormInstance = {
  on(event: FormEventName, handler: (payload?: any) => void): FormInstance;
  submit(): Promise<void>;
};
```

**Example:**

```javascript theme={null}
const form = Proview.form.init({
  dsn: 'project-dsn',
  projectId: 'project-123',
  credential: firebaseCredential,
});

form.mount({
  formId: 'form-123',
  containerId: 'form-container',
  mountMode: { mode: 'sidepanel' },
});

const formInstance = await form.open();

formInstance
  .on('ready', () => console.log('Form ready'))
  .on('submitted', () => {
    console.log('Form submitted');
    // Handle success
  })
  .on('error', ({ message }) => {
    console.error('Form error:', message);
  });
```

***

## User Object

After initializing the form module, `Proview.user` provides a Firebase-compatible user object accessible globally.

**User Interface**

```javascript theme={null}
type User = {
  uid: string;                      // User's unique ID
  email: string | null;             // User's email address
  displayName: string | null;       // User's display name
  emailVerified: boolean;           // Email verification status
  isAnonymous?: boolean;            // Is anonymous user
  metadata?: UserMetadata;          // Creation and last sign-in time
  providerData?: ProviderData[];    // Provider-specific info

  // Methods
  getIdToken(forceRefresh?: boolean): Promise<string>;
  getIdTokenResult(forceRefresh?: boolean): Promise<IdTokenResult>;
};
```

**Example:**

```javascript theme={null}
const firebaseCredential = Proview.auth.FirebaseAuthStrategy({
  token: 'your-firebase-auth-token',
});

const form = Proview.form.init({
  dsn: 'project-dsn',
  projectId: 'project-123',
  credential: firebaseCredential,
});

// Access user properties globally
const user = Proview.user;
console.log(user.uid);
console.log(user.email);
console.log(user.displayName);
console.log(user.emailVerified);

// Get ID token
const idToken = await user.getIdToken();

// Force refresh token
const freshToken = await user.getIdToken(true);
```

***

## Firebase Authentication

### `Proview.auth.FirebaseAuthStrategy(config)`

Creates a Firebase authentication credential for use with the Proview SDK modules.

**Input**

```javascript theme={null}
type FirebaseAuthStrategyConfig = {
  token: string;  // Required: Firebase authentication token
};
```

**Returns** — `FirebaseAuthStrategy`

A credential object that can be passed to any Proview SDK module initialization.

**Example:**

```javascript theme={null}
// Initialize Firebase credential with token
const firebaseCredential = Proview.auth.FirebaseAuthStrategy({
  token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
});

// Use with form module
const form = Proview.form.init({
  dsn: 'project-dsn',
  projectId: 'project-123',
  credential: firebaseCredential,
});
```

***

## Form Events

The `FormInstance` emits events that you can subscribe to using the `on()` method.

**Event names and payloads**

| Event       | Payload               | Description                 |
| ----------- | --------------------- | --------------------------- |
| `ready`     | `void`                | Form loaded and ready       |
| `submitted` | `void`                | Form submitted successfully |
| `error`     | `{ message: string }` | Error occurred              |

**Example:**

```javascript theme={null}
form
  .on('ready', () => {
    // Form is ready for input
  })
  .on('submitted', () => {
    // Form was submitted successfully
  })
  .on('error', ({ message }) => {
    // Handle form error
    alert(`Error: ${message}`);
  });
```

***

## Mount Modes

The form module supports three layout modes for the form UI.

| Mode          | Value         | Behavior                        |
| ------------- | ------------- | ------------------------------- |
| **Sidepanel** | `'sidepanel'` | Slides in from side of viewport |
| **Popup**     | `'popup'`     | Centered modal overlay          |
| **Inline**    | `'inline'`    | Embedded in the page flow       |

**Example:**

```javascript theme={null}
// Sidepanel mode
const mounted1 = form.mount({
  formId: 'form-123',
  containerId: 'form-container',
  mountMode: {
    mode: 'sidepanel',
  },
});

// Popup mode
const mounted2 = form.mount({
  formId: 'form-123',
  containerId: 'form-container',
  mountMode: {
    mode: 'popup',
  },
});

// Inline mode
const mounted3 = form.mount({
  formId: 'form-123',
  containerId: 'form-container',
  mountMode: {
    mode: 'inline',
  },
});
```

***

## Error Handling

Form errors follow a consistent structure.

**Error Structure**

```javascript theme={null}
type FormError = {
  code: string;    // Error code for programmatic handling
  message: string; // Human-readable error message
};
```

**Common Error Codes**

| Code              | Description                     |
| ----------------- | ------------------------------- |
| `FORM_LOAD_ERROR` | Failed to load form             |
| `PANEL_ERROR`     | Panel rendering error           |
| `TOKEN_INVALID`   | Authentication token is invalid |
| `TOKEN_EXPIRED`   | Session token expired           |
| `AUTH_FAILED`     | Authentication failed           |
| `FETCH_FAILED`    | Network or API request failed   |

**Example:**

```javascript theme={null}
try {
  const firebaseCredential = Proview.auth.FirebaseAuthStrategy({
    token: 'your-firebase-auth-token',
  });

  const form = Proview.form.init({
    dsn: 'project-dsn',
    projectId: 'project-123',
    credential: firebaseCredential,
  });

  const mounted = form.mount({
    formId: 'form-123',
    containerId: 'form-container',
    mountMode: {
      mode: 'popup',
    },
  });

  const formInstance = await form.open();

  formInstance.on('error', ({ message }) => {
    console.error('Form error:', message);
    // Handle error in UI
  });

} catch (error) {
  switch (error.code) {
    case 'AUTH_FAILED':
      alert('Authentication failed. Please log in again.');
      break;

    case 'TOKEN_INVALID':
      alert('Invalid authentication token.');
      break;

    case 'TOKEN_EXPIRED':
      alert('Session expired. Please log in again.');
      break;

    case 'FORM_LOAD_ERROR':
      alert('Failed to load form. Please try again.');
      break;

    case 'PANEL_ERROR':
      alert('Failed to render form panel. Check your page setup.');
      break;

    case 'FETCH_FAILED':
      alert('Network error. Please check your connection.');
      break;

    default:
      alert(`Error: ${error.message}`);
      break;
  }
}
```
