Managing Data Flow
The @veeva/vault JavaScript package allows you to send and receive data from PageController.
From your client code, you can:
- Retrieve data from the server when a user loads your Custom Page in Vault
- Trigger a page reload
- Send an event with data to the server and handle the returned data
- Send a request to Vault API
The definePage() function provides these key parameters for data management:
| Parameter | Description |
|---|---|
data | Data returned from PageController's onLoad() response |
element | Root HTML element to append to when writing client code |
pageContext | Page context providing the reload() function |
sendEvent | Function to send an event to the PageController |
Loading Server Data
Section link for Loading Server DataLoading 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>
);
});Reloading the Page
Section link for Reloading the PageYou 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>
...Sending Events
Section link for Sending EventsFrom 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);
...Using Vault API
Section link for Using Vault APIYou 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.
Controlling Navigation
Section link for Controlling NavigationCustom 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.
Retrieving Server-Generated URLs
Section link for Retrieving Server-Generated URLsAccess 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>
`;Location & History
Section link for Location & HistoryThe 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);
};
});