Prerender components
To optimize your userβs experience when ThoughtSpot is embedded into your application, we recommend using the prerender method.
Prerenderπ
You can load ThoughtSpot components that are not specific to the userβs session before your application user accesses the embedded content. With this, the amount of ThoughtSpot assets left to load when the user accesses the embedded content is reduced.
When to use prerenderπ
Use prerender in the following cases:
-
if you have applications that do not have ThoughtSpot on the landing page.
-
if you are embedding ThoughtSpot Liveboards in your applications.
How it worksπ
Pre-render allows developers to pre-load the ThoughtSpot application in the background before the user navigates to the embedded content.
It allows you to create a placeholder element on the page for the Liveboard to eventually populate. To preload components, you must place this element into a section of your application that will be viewed before the Liveboard. For example, it is common for analytics applications to have a custom-built landing page that directs users to relevant pieces of embedded content. This would be an ideal place to preload the component, so the frame is ready to render by the time the user clicks on a specific link.
The following figure illustrates the benefits of the pre-render method:
How to implement prerenderπ
Depending on the framework and project, you can implement this using Standard JavaScript or React.
Standard JSπ
If using Javascript:
-
Create a container for the Liveboard and a placeholder.
For this approach, you require two containers:
-
a
div
container withabsolute
position. This will eventually be used to render the Liveboard. -
a placeholder
div
. This is the container designated for the Liveboard, which you will set as the primary embed container in your application code. When it is time to load a Liveboard, move the prerenderdiv
on top of the placeholderdiv
.<div id="placeholder"></div> <div id="prerender"></div>
#prerender{ position: absolute; opacity: 0; left: 0; top: 0; height: 0; width: 0; }
-
-
PreRender ThoughtSpot
Inside the prerender
div
, you can create a placeholder for Liveboard embedding. Before calling the Liveboard GUID, callprerenderGeneric
to start the load process for the primary embed and transfer the bulk of the information needed by ThoughtSpot to the client browser.let renderDiv = document.getElementById("prerender"); let embed = new LiveboardEmbed(renderDiv, { frameParams: { height: "1200px" } }); embed.prerenderGeneric();
-
Render the embedded Liveboard
When it is time for the user to view a specific liveboard, move the
prerender div
onto the placeholder, and instruct the Liveboard Embed to load the required content. To do this, use thenavigateToLiveboard
function on the embed object://Navigate embed container to new liveboard id let liveboardID = "16b8c2e2-edfc-4e42-8827-98387f384b1b" embed.navigateToLiveboard(liveboardID) //Obtain the current bounds of the placeholder element let placeholderDiv = document.getElementById("placeholder"); const coords = placeholderDiv.getBoundingClientRect(); const offset = getOffset(placeholderDiv); //Move the renderer into those bounds renderDiv.style.opacity = 1; renderDiv.style.top = offset.top; renderDiv.style.left = offset.left; renderDiv.style.width = coords.width; renderDiv.style.height = coords.height; function getOffset(el) { var _x = 0; var _y = 0; while (el && !isNaN(el.offsetLeft) && !isNaN(el.offsetTop)) { _x += el.offsetLeft - el.scrollLeft; _y += el.offsetTop - el.scrollTop; el = el.offsetParent; } return { top: _y, left: _x }; }
Reactπ
If using React, make sure the container is not continuously reloaded with state changes. You can use a context provider to achieve this. For more information, see https://react.dev/learn/passing-data-deeply-with-context.
const prerenderdLiveboardContext = createContext<any>({});
This approach requires two containers. The first is a div
with absolute position. This will eventually be used to render the liveboard.
The second is a placeholder. This is the container designated for the Liveboard, which you will set as the primary embed container in your application code. When loading the Liveboard, move the prerender div
on top of the placeholder div.
-
Create render shell
This is a
div
element with absolute position. Use context variables to control the divβs visibility and coordinate position. This div also holds the embedded Liveboard, and theliveboardId
is set by the respective context variable.By default, this
div
will be invisible and placed into a corner of the page (0 coordinates), with noliveboardId
.export const PrerenderedLiveboardShell = () => { const ref = useRef(null); const lb = useRef<LiveboardEmbed | null>(null); const { isVisible, liveboardId, coords } = useContext( prerenderdLiveboardContext ); return ( <div id="prerender" style={{ opacity: isVisible ? 1 : 0, ...coords, position: "absolute" }} ref={ref} ></div> ); }
-
Pre-render the embed container
-
Create a Liveboard embed within this
div
. -
Before calling the Liveboard GUID, call
prerenderGeneric
to start the load process for the primary embed and transfer the bulk of the information needed by ThoughtSpot to render content to the client browser. -
Pass an empty array into
useEffect
.
useEffect(() => { if (!ref.current) { return; } lb.current = new LiveboardEmbed(ref.current, { frameParams: { height: "1200px" } }); lb.current.prerenderGeneric(); }, []);
-
-
Navigate to Liveboard
Update the render container when the user is ready to view the Liveboard. For this, use the previously defined context variable that sets the
liveboardId
, and leverageuseEffect
to register the changes to this ID. When the Liveboard ID is updated, render the new Liveboard by using thenavigateToLiveboard
function:useEffect(() => { if (!liveboardId) { return; } lb.current?.navigateToLiveboard(liveboardId); }, [liveboardId]);
-
Create context provider
To manage context variables and render the shell we next need to create a provider component:
export const PrerenderdLiveboardProvider = ({ children }) => { const [isVisible, setIsVisible] = useState(false); const [liveboardId, setLiveboardId] = useState(); const [coords, setCoords] = useState({ left: 0, top: 0, height: 0, width: 0 }); return ( <prerenderdLiveboardContext.Provider value={{ isVisible, setIsVisible, liveboardId, setLiveboardId, coords, setCoords }} > {children} <PrerenderedLiveboardShell /> </prerenderdLiveboardContext.Provider> ); };
-
Add this code to your application
In this example, the primary content is in a component named
LiveboardBrowser
. It includes a list of different liveboards that a user can choose from, and a space on the page to render the Liveboard. The IDs are hard-coded in this example. However, you can populate this via a REST call.init({ thoughtSpotHost: "https://my.thoughtspot.cloud/", authType: AuthType.None, // AuthType.Passthrough }) function App() { return ( <div className="App"> <PrerenderdLiveboardProvider> <LiveboardBrowser></LiveboardBrowser> </PrerenderdLiveboardProvider> </div> ); }
-
Render a Liveboard
-
Set our context variables
-
Specify the GUID of the Liveboard
-
Set coordinates for the element the shell will overlay
-
Set visibility to
true
.
function toggleLiveboardSelect(e){ setLiveboardId(e.target.value); const coords = ref.current.getBoundingClientRect(); const offset = getOffset(ref.current); setCoords({ height: coords.height, width: coords.width, top: offset.top, left: offset.left }); setIsVisible(true); }
-