Implementing FormHostProvider
FormHostProvider is a React component you write once in your own project. It connects the Buildocs form to your backend — routing form events through your API and providing an auth token at runtime.
Every integration requires it. Without it, the form cannot load its definition or make any API calls.
How it works
- Your backend exposes a token endpoint.
FormHostProviderfetches that token on mount. - You call
useBuildocsApi(yourBackendUrl, token)to get pre-wired HTTP methods that route to your backend. - You build a
HostBridgeobject mapping each form event to a method call. - You render
BuildocsHostProviderwith the bridge, wrapping your children.
The form definition is still fetched directly from Buildocs using useBuildocsApi() (no custom URL).
Step 1 — Create the file
Create src/provider/FormHostProvider.tsx and paste in the boilerplate below.
import React, { useEffect, useState } from 'react';
import {
type TLoadForm,
type HostBridge,
type RunEventArgs,
type UploadArgs,
ChunkRequestArgs,
DeleteFileEventArgs,
DownloadFileEventArgs,
FileMetaEventArgs,
GetLinkedFileMetaEventArgs,
BuildocsHostProvider,
useBuildocsApi,
useViewport,
} from '@buildocsdev/sdk';
interface FormHostProviderProps {
readonly children: React.ReactNode;
}
export function FormHostProvider({ children }: FormHostProviderProps) {
const { isMobileDevice, width, height } = useViewport();
const [token, setToken] = useState<string | undefined>(undefined);
const buildocsApi = useBuildocsApi();
const myApiUrl = 'https://your-backend.com/api/v1/formspublic';
const myApi = useBuildocsApi(myApiUrl, token);
useEffect(() => {
fetch(`${myApiUrl}/token`, { method: 'POST' })
.then(r => r.json())
.then((d: { token: string }) => setToken(d.token))
.catch(e => console.error('Failed to fetch token:', e));
}, []);
const hostBridge: HostBridge = {
viewPort: { isMobileDevice, width, height },
runFormEvent: async (args: RunEventArgs) => {
return await myApi.runEvent(args, '/runevent');
},
runFormUploadFiles: async (args: UploadArgs) => {
return await myApi.uploadFiles(args, '/uploadfiles');
},
runFormDeleteFileEvent: async (args: DeleteFileEventArgs) => {
return await myApi.deleteFile(args, '/deletefile');
},
runFormDownloadFileEvent: async (args: DownloadFileEventArgs) => {
return await myApi.downloadFile(args, '/downloadfile');
},
runFormGetLinkedFileEvent: async (args: GetLinkedFileMetaEventArgs) => {
return await myApi.getLinkedFile(args, '/getlinkedfile');
},
runFormGetLinkedFileMetaEvent: async (args: GetLinkedFileMetaEventArgs) => {
return await myApi.getLinkedFileMetaEvent(args, '/getlinkedfilemeta');
},
runFormGetLinkedFileByChunks: async (args: ChunkRequestArgs) => {
return await myApi.getLinkedFileByChunks(args, '/getlinkedfilebychunks');
},
runFormGetPresignedUrl: async (args: FileMetaEventArgs) => {
return await myApi.getPresignedUrl(args, '/getpresignedurl');
},
runLoadFormEvent: async (args: TLoadForm) => {
return await buildocsApi.fetchFormDefinitionWithMeta(args.formCode);
},
};
return (
<BuildocsHostProvider hostBridge={hostBridge}>
{children}
</BuildocsHostProvider>
);
}
Step 2 — Wrap your app
FormHostProvider must be nested inside BuildocsProvider. Place both providers high enough in your tree to cover all Form components.
import { BuildocsProvider } from '@buildocsdev/sdk';
import { Form } from '@buildocsdev/sdk/form';
import { FormHostProvider } from './provider/FormHostProvider';
function App() {
return (
<BuildocsProvider apiKey="your-api-key">
<FormHostProvider>
<Form params={{ formCode: "your-form-code", guid: "new" }} />
</FormHostProvider>
</BuildocsProvider>
);
}
Token authentication
The token is fetched from your backend on mount and passed to useBuildocsApi as its second argument. All subsequent event calls include it automatically.
const myApi = useBuildocsApi(myApiUrl, token);
Your backend's /token endpoint should return:
{ "token": "<your-auth-token>" }
useBuildocsApi — two instances
Notice the boilerplate uses useBuildocsApi twice:
| Instance | Purpose |
|---|---|
useBuildocsApi() | Fetches the form definition directly from Buildocs |
useBuildocsApi(myApiUrl, token) | Routes all form events through your own backend |
The form definition (runLoadFormEvent) is always fetched directly from Buildocs. All other events go through your backend.
Pre-populating form data
Pass existing data as the second argument to fetchFormDefinitionWithMeta. Keys must match the Name of each field in the Form Builder exactly.
runLoadFormEvent: async (args: TLoadForm) => {
const existingData = await myDb.getRecord(args.guid);
return await buildocsApi.fetchFormDefinitionWithMeta(args.formCode, existingData);
},
HostBridge methods
Each method maps to a form action and must have a corresponding endpoint implemented in your own backend. The final URL for each call is myApiUrl + customPath.
| HostBridge method | Default path | Action |
|---|---|---|
runFormEvent | /runevent | Button and field events |
runFormUploadFiles | /uploadfiles | File uploads |
runFormDeleteFileEvent | /deletefile | File deletion |
runFormDownloadFileEvent | /downloadfile | File downloads |
runFormGetLinkedFileEvent | /getlinkedfile | Linked file retrieval |
runFormGetLinkedFileMetaEvent | /getlinkedfilemeta | Linked file metadata |
runFormGetLinkedFileByChunks | /getlinkedfilebychunks | Chunked file download |
runFormGetPresignedUrl | /getpresignedurl | Presigned URL generation |
runLoadFormEvent | — | Form definition load (direct to Buildocs) |
See the FormHostProvider API reference for request payload details for each method.