Skip to content

Managing Data Flow

The @veeva/vault JavaScript package allows you to send and receive data from PageController.

From your client code, you can:

The definePage() function provides these key parameters for data management:

ParameterDescription
dataData returned from PageController's onLoad() response
elementRoot HTML element to append to when writing client code
pageContextPage context providing the reload() function
sendEventFunction to send an event to the PageController

Loading your Custom Page in the browser calls the PageController’s onLoad() method. In the client code, the data parameter provides the data returned from the onLoad() method.

For example, if the PageController’s onLoad() method returns the userId of the currently authenticated user, you can get the user ID from the data parameter and display it on the page:

import React from 'react'; import { createRoot } from 'react-dom/client'; import { definePage } from '@veeva/vault'; export default definePage(({ data = {}, element }) => { const { userId = '<userId>' } = data; const root = createRoot(element); root.render( <div>Hello user {userId}!</div> ); });

You can trigger a page reload from the client using the pageContext parameter’s reload() function. This function calls the PageController’s onLoad() method.

export default definePage(({ element, pageContext }) => { ... <button onClick={() => pageContext.reload()} >Refresh</button> ...

From the client code, use sendEvent() to send an event with data to the PageController. This calls the PageController’s onEvent() method, which processes the data and returns it as a JSON response.

export default definePage(({ element, sendEvent }) => { ... async function fetchData() { const serverResponse = await sendEvent("myEvent", requestData); ...

You can use Vault API directly from your client code by importing the vaultApiClient. You can retrieve Vault data using the vaultApiClient.fetch() async function:

import { vaultApiClient } from "@veeva/vault"; ... async function fetchDocuments() { vaultApiClient.fetch('/v25.1/objects/documents', { headers: { "X-VaultAPI-ClientID": "hello-world", "Content-Type": "application/json", }, }) .then(...); ...

Vault automatically uses the host name of the currently authenticated Vault and appends the /api suffix.

We recommend setting a unique X-VaultAPI-ClientID header value to track in the API Usage Logs.

API calls made from Custom Pages count towards API rate limits and are filtered with Client ID Filtering.

Users do not need API permission to view a Custom Page that calls Vault API from code.

Custom Pages can control navigation and history from client code using custom URLs to Vault locations and the vaultLocation and history objects. For example, this allows you to add breadcrumb links or a custom Back button to a Custom Page.

Access UrlService URLs using the data parameter in your client code. The server code must add URLs to the response to make them available to the client code.

In the following example, the server code has added the urls array to the response data. The client code can access this data using data.urls, as in the following example:

import { definePage } from '@veeva/vault'; export default definePage(({ element, data }) => { element.innerHTML = ` <div> <h1>Vault Location URLs</h1> <div> <ul> ${data?.urls?.map(url => `<li><a href="${url}">${url}</a></li>`).join('') ?? ''} </ul> </div> </div> `;

The window.vaultLocation object allows access to the browser’s location object in Vault.

The browser’s window.history object is also available in Vault and allows navigation through a user’s session history. Note that the history.pushState() and history.replaceState() functions are not available.

The following example creates a Custom Page with a button that navigates to the previous page and buttons that set and display the current browser location. The server code has set homeUrl with a single URL string, and the second button sets the current location to that URL via data.homeUrl.

import { definePage } from '@veeva/vault'; export default definePage(({ element, data }) => { element.innerHTML = ` <div> <h1>Custom Page</h1> <h2>Navigation Buttons</h2> <button id="historyBack">Back</button> <button id="setLocation">Set location</button> <button id="locationHref">Get location</button> </div> `; element.querySelector('#historyBack').onclick = () => { history.back(); }; element.querySelector('#setLocation').onclick = () => { vaultLocation.href = data.homeUrl; }; element.querySelector('#locationHref').onclick = () => { alert(vaultLocation.href); }; });