PDFViewer
A full-featured PDF viewing component with form fields, digital signatures, zoom controls, and document submission capabilities.
Import
import { PDFViewer } from '@doccentral/react';Basic Usage
<PDFViewer
documentId="doc_abc123"
documentUrl="https://example.com/document.pdf"
onSubmit={(payload) => console.log('Submitted:', payload)}
/>Props
Required Props
| Prop | Type | Default | Description |
|---|---|---|---|
documentId* | string | - | Unique identifier for the document. Used for submission tracking. |
documentUrl* | string | - | URL to the PDF document. Can be a signed URL from your backend. |
Display Options
| Prop | Type | Default | Description |
|---|---|---|---|
initialScale | number | 1 | Initial zoom level. 1 = 100%, 0.5 = 50%, 2 = 200%. |
showToolbar | boolean | true | Show/hide the toolbar with navigation and zoom controls. |
editable | boolean | true | Allow users to interact with and fill form fields. |
showFieldTools | boolean | true | Show field creation tools in the toolbar (requires editable=true). |
height | string | number | "100%" | Height of the viewer container. |
className | string | - | Additional CSS class names for the container. |
style | React.CSSProperties | - | Inline styles for the container. |
Initial Data
| Prop | Type | Default | Description |
|---|---|---|---|
initialFields | AnyFieldDefinition[] | [] | Pre-defined fields to display on the document. |
Event Callbacks
| Prop | Type | Default | Description |
|---|---|---|---|
onDocumentLoad | (pages: PageInfo[]) => void | - | Called when the PDF is successfully loaded. |
onDocumentError | (error: Error) => void | - | Called when the PDF fails to load. |
onFieldAdd | (field: AnyFieldDefinition) => void | - | Called when a new field is added. |
onFieldUpdate | (fieldId: string, updates: Partial<AnyFieldDefinition>) => void | - | Called when a field position or properties change. |
onFieldValueChange | (fieldId: string, value: AnyFieldValue) => void | - | Called when a field value changes. |
onFieldRemove | (fieldId: string) => void | - | Called when a field is removed. |
onBeforeSubmit | (payload: DocumentSubmissionPayload) => boolean | Promise<boolean> | - | Called before submission. Return false to cancel. |
onSubmit | (payload: DocumentSubmissionPayload) => void | Promise<void> | - | Called after successful submission. |
onSubmitError | (error: Error) => void | - | Called when submission fails. |
Examples
Basic Document Viewer
function BasicViewer() {
return (
<div style={{ height: '600px' }}>
<PDFViewer
documentId="doc_123"
documentUrl="/contracts/agreement.pdf"
showToolbar={true}
editable={false}
/>
</div>
);
}With Pre-defined Fields
1const fields = [
2 {
3 id: 'name_field',
4 type: 'text' as const,
5 page: 1,
6 x: 0.1,
7 y: 0.3,
8 width: 0.3,
9 height: 0.04,
10 required: true,
11 editable: true,
12 label: 'Full Name',
13 placeholder: 'Enter your full name',
14 },
15 {
16 id: 'signature_field',
17 type: 'signature' as const,
18 page: 1,
19 x: 0.1,
20 y: 0.7,
21 width: 0.3,
22 height: 0.1,
23 required: true,
24 editable: true,
25 label: 'Signature',
26 },
27 {
28 id: 'date_field',
29 type: 'date' as const,
30 page: 1,
31 x: 0.5,
32 y: 0.7,
33 width: 0.2,
34 height: 0.04,
35 required: true,
36 editable: true,
37 label: 'Date',
38 },
39];
40
41function DocumentWithFields() {
42 return (
43 <PDFViewer
44 documentId="contract_456"
45 documentUrl="/contracts/nda.pdf"
46 initialFields={fields}
47 onFieldValueChange={(fieldId, value) => {
48 console.log(`Field ${fieldId} changed:`, value);
49 }}
50 />
51 );
52}Full Submission Flow
1function ContractSigningPage({ documentId }: { documentId: string }) {
2 const [isSubmitting, setIsSubmitting] = useState(false);
3 const [submitSuccess, setSubmitSuccess] = useState(false);
4 const router = useRouter();
5
6 const handleBeforeSubmit = async (payload: DocumentSubmissionPayload) => {
7 // Validate all required fields are filled
8 const requiredFields = payload.fields.filter(f => f.required);
9 const missingFields = requiredFields.filter(f => !f.value);
10
11 if (missingFields.length > 0) {
12 alert('Please fill all required fields');
13 return false;
14 }
15
16 return true;
17 };
18
19 const handleSubmit = async (payload: DocumentSubmissionPayload) => {
20 setIsSubmitting(true);
21
22 // The SDK automatically sends to DocCentral API
23 // You can also send to your own backend
24 await fetch('/api/contracts/complete', {
25 method: 'POST',
26 headers: { 'Content-Type': 'application/json' },
27 body: JSON.stringify({
28 documentId: payload.documentId,
29 submittedAt: payload.submittedAt,
30 }),
31 });
32
33 setSubmitSuccess(true);
34 setIsSubmitting(false);
35
36 // Redirect after 2 seconds
37 setTimeout(() => {
38 router.push('/contracts/completed');
39 }, 2000);
40 };
41
42 const handleSubmitError = (error: Error) => {
43 setIsSubmitting(false);
44 alert(`Submission failed: ${error.message}`);
45 };
46
47 if (submitSuccess) {
48 return (
49 <div className="flex flex-col items-center justify-center h-64">
50 <CheckCircle className="w-16 h-16 text-green-500" />
51 <h2 className="mt-4 text-xl font-semibold">Document Submitted!</h2>
52 <p className="text-gray-500">Redirecting...</p>
53 </div>
54 );
55 }
56
57 return (
58 <PDFViewer
59 documentId={documentId}
60 documentUrl={`/api/documents/${documentId}/download`}
61 onDocumentLoad={(pages) => {
62 console.log(`Loaded ${pages.length} pages`);
63 }}
64 onBeforeSubmit={handleBeforeSubmit}
65 onSubmit={handleSubmit}
66 onSubmitError={handleSubmitError}
67 />
68 );
69}Field Positioning
Fields use normalized coordinates (0-1) relative to page dimensions. This ensures fields are positioned correctly regardless of zoom level or rendering size.
// Field at 10% from left, 30% from top
// Width: 30% of page, Height: 4% of page
{
x: 0.1,
y: 0.3,
width: 0.3,
height: 0.04,
}Coordinate System
x: 0= left edge,x: 1= right edgey: 0= top edge,y: 1= bottom edge- Width and height are also normalized (0-1)
Toolbar Features
The default toolbar includes:
- Page Navigation: Previous/next page, page number input
- Zoom Controls: Zoom in, zoom out, fit to width/page
- Field Tools: Add text, signature, checkbox, date, initials fields
- Submit Button: Validates and submits the document
Styling
Customize the viewer appearance:
<PDFViewer
documentId="..."
documentUrl="..."
className="my-custom-viewer"
style={{
borderRadius: '8px',
boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)',
}}
/>
/* CSS */
.my-custom-viewer {
background: #f5f5f5;
}
.my-custom-viewer .doccentral-pdf-toolbar {
background: #1a1a1a;
color: white;
}Error Handling
<PDFViewer
documentId="..."
documentUrl="..."
onDocumentError={(error) => {
if (error.message.includes('404')) {
showNotification('Document not found');
} else if (error.message.includes('403')) {
showNotification('Access denied');
} else {
showNotification('Failed to load document');
logError(error);
}
}}
onSubmitError={(error) => {
if (error.message.includes('validation')) {
showNotification('Please fill all required fields');
} else {
showNotification(`Submission failed: ${error.message}`);
}
}}
/>TypeScript Types
import type {
PDFViewerProps,
AnyFieldDefinition,
AnyFieldValue,
DocumentSubmissionPayload,
PageInfo,
FieldType,
} from '@doccentral/react';
// Field types: 'text' | 'signature' | 'checkbox' | 'date' | 'initials'