How to Embed Bold BI Dashboard Using React Native CLI with Node.js?
This article demonstrates how to integrate Bold BI dashboards within a React Native CLI application, using Node.js as the backend. The purpose of this application is to show how to render the dashboard available on your Bold BI server.
Requirements/Prerequisites
NOTE: Node.js versions 18.20 to 22.14 are supported.
How to Run the Sample
-
Please obtain the React Native CLI with Node.js sample from GitHub.
-
Ensure that you have enabled embedded authentication on the
Embed Settings
page. If it is not currently enabled, refer to the following image or the detailed instructions to enable it. -
To download the
embedConfig.json
file, please follow this link for reference. Additionally, you can refer to the following image for visual guidance. -
Copy the downloaded
embedConfig.json
file and paste it into the designated location within the application. Please ensure that you have placed it in the correct location, as shown in the following image. -
Open the
Nodejs
sample in Visual Studio Code. -
To install all dependent packages, use the command
npm install
. -
Then, run the back-end
Node.js
sample using the commandnode embed.js
. -
Open the
React Native CLI
project in Android Studio. -
To install all the required packages, use the command
npm install
. -
Add a virtual device and run the Metro bundler in the terminal using the command
npx react-native start
. -
Finally, run the sample in the Android emulator with the command
npx react-native run-android
.
NOTE: If the API host is already in use, modify the port number in
embed.js
according to your preference and updateApp.js
in the React Native application accordingly.
How the Sample Works
- The WebView component is used to render the dashboard.
const customHTML = `
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body style="margin:0;padding:0;overflow:hidden;">
<div id="dashboardContainer" style="width:100%;height:100vh;"></div>
</body>
</html>`;
return (
<WebView
source={{ html: customHTML }}
mixedContentMode="always"
injectedJavaScript={injectedJavaScript}
javaScriptEnabled={true}
originWhitelist={["*"]}
onMessage={(event) => console.log("WebView message:", event.nativeEvent.data)}
/>
);
- The WebView loads a JavaScript snippet that dynamically injects the Bold BI embedding script and initializes the dashboard.
const injectedJavaScript = `
(function() {
function loadScript(url, callback) {
var script = document.createElement('script');
script.src = url;
script.onload = callback;
script.onerror = function() {
window.ReactNativeWebView.postMessage("Script loading failed.");
};
document.head.appendChild(script);
}
function renderDashboard() {
try {
const dashboard = BoldBI.create({
serverUrl: "${ServerUrl + '/' + SiteIdentifier}",
dashboardId: "${DashboardId}",
embedContainerId: "dashboardContainer",
authorizationServer: {
url: "${apiHost + authorizationServerAPI}"
}
});
dashboard.loadDashboard();
} catch (error) {
console.error("Error loading dashboard:", error);
}
}
loadScript('https://cdn.boldbi.com/embedded-sdk/v11.2.7/boldbi-embed.js', renderDashboard);
})();
true;
`;
- Before rendering, authorize the server URL by making a call to the AuthorizationServer API using the provided embedConfig values.
app.post('/authorizationserver', async function (req, response){
var embedQuerString = req.body.embedQuerString;
var dashboardServerApiUrl = req.body.dashboardServerApiUrl;
embedQuerString += "&embed_user_email=" + userEmail;
embedQuerString += "&embed_server_timestamp=" + Math.round((new Date()).getTime() / 1000);
var embedSignature = "&embed_signature=" + GetSignatureUrl(embedQuerString);
var embedDetailsUrl = "/embed/authorize?" + embedQuerString+embedSignature;
var serverProtocol = url.parse(dashboardServerApiUrl).protocol == 'https:' ? https : http;
serverProtocol.get(dashboardServerApiUrl+embedDetailsUrl, function(res){
var str = '';
res.on('data', function (chunk) {
str += chunk;
});
res.on('end', function () {
response.send(str);
});
});
})
function GetSignatureUrl(queryString)
{
var keyBytes = Buffer.from(embedSecret);
var hmac = crypto.createHmac('sha256', keyBytes);
data = hmac.update(queryString);
gen_hmac= data.digest().toString('base64');
return gen_hmac;
}
Steps to Create a New React and Node.js Application to Embed a Dashboard
-
Create a folder in your desired location and open it in Visual Studio Code.
-
Open the terminal in Visual Studio Code. Please refer to the image below.
-
Ensure that you have enabled embed authentication on the
Embed Settings
page. If it is not currently enabled, refer to the following image or detailed instructions to enable it.
-
To download the
embedConfig.json
file, please follow this link for reference. Additionally, you can refer to the following image for visual guidance.
-
Copy the downloaded
embedConfig.json
file and paste it into the designated location within the application. Please ensure that it is placed in the correct location, as shown in the image below. -
Next, create a JavaScript file named
embed.js
. Within this file, create an API endpoint called/authorizationserver/get
that utilizes theGetSignatureUrl()
method to generate the required algorithm. In this API, append theembedQueryString
,userEmail
, and the value obtained from theGetSignatureUrl()
method as query parameters in the URL to retrieve the details of a specific dashboard.var fs = require("fs"); var http = require("http"); var https = require("https"); var url = require("url"); var express = require('express'); var cors = require('cors'); var app = express(); var crypto = require('crypto'); const path = require('path'); app.use(cors()); //Parse JSON bodies (as sent by API clients). app.use(express.json()); //Assign a port number for an API to run. const port = 8080; let appconfig; try { appconfig = JSON.parse(fs.readFileSync('embedConfig.json')); } catch (error) { console.error('Error: embedConfig.json file not found.'); process.exit(1); } var embedSecret = appconfig.EmbedSecret; var userEmail = appconfig.UserEmail; app.post('/authorizationserver', async function (req, response){ var embedQuerString = req.body.embedQuerString; var dashboardServerApiUrl = req.body.dashboardServerApiUrl; embedQuerString += "&embed_user_email=" + userEmail; embedQuerString += "&embed_server_timestamp=" + Math.round((new Date()).getTime() / 1000); var embedSignature = "&embed_signature=" + GetSignatureUrl(embedQuerString); var embedDetailsUrl = "/embed/authorize?" + embedQuerString+embedSignature; var serverProtocol = url.parse(dashboardServerApiUrl).protocol == 'https:' ? https : http; serverProtocol.get(dashboardServerApiUrl+embedDetailsUrl, function(res){ var str = ''; res.on('data', function (chunk) { str += chunk; }); res.on('end', function () { response.send(str); }); }); }) function GetSignatureUrl(queryString) { var keyBytes = Buffer.from(embedSecret); var hmac = crypto.createHmac('sha256', keyBytes); data = hmac.update(queryString); gen_hmac= data.digest().toString('base64'); return gen_hmac; } app.get('/getdetails', (req, res) => { const serverEmbedConfigData = path.join(__dirname, 'embedConfig.json'); const jsonData = fs.readFileSync(serverEmbedConfigData, 'utf8'); const parsedData = JSON.parse(jsonData); const clientEmbedConfigData = { DashboardId: parsedData.DashboardId, ServerUrl: parsedData.ServerUrl, SiteIdentifier: parsedData.SiteIdentifier, EmbedType: parsedData.EmbedType, Environment: parsedData.Environment }; res.send(clientEmbedConfigData); }); app.listen(port, () => { console.log(`Server is running on port ${port}`); });
NOTE: If the API host is already in use, modify the port number in
embed.js
according to your preference, and updateApp.js
in the React Native application accordingly. -
Create a new file and name it
package.json
. Installing thepackages
listed in the following dependencies section is essential.{ "version": "1.0.0", "description": "", "main": "embed.js", "dependencies": { "cors": "^2.8.5", "express": "^4.17.3" }, "devDependencies": {}, "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC" }
-
Run the following command in the terminal:
npm install
. -
To run the Node.js sample, use the following command in Visual Studio Code:
npm start
. -
Create a new React Native project called
ReactNativeCLI
using the following command:npx @react-native-community/cli init ReactNativeCLI
-
After creating the React Native CLI sample, open the project in Android Studio.
-
Within the React Native CLI sample, create a new file named
App.js
. In theApp.js
file, add the following code to import the required modules, define the HomeScreen component, and use auseEffect
hook to fetch the dashboard details when the component loads.import React, { useEffect, useState } from "react"; import { WebView } from "react-native-webview"; export default function HomeScreen() { const [embedConfig, setEmbedConfig] = useState(null); const apiHost = "http://10.0.2.2:8080"; // Use emulator IP instead of localhost const authorizationServerAPI='/authorizationserver'; const getDetailsUrl='/getdetails'; useEffect(() => { fetch(apiHost+getDetailsUrl) .then((response) => response.json()) .then((data) => setEmbedConfig(data)) .catch((error) => console.error("Error fetching embed config:", error)); }, []); if (!embedConfig) return null; const { ServerUrl, DashboardId, SiteIdentifier } = embedConfig;
-
Inside the
App.js
file, add the following code: create a DOM element with the IDdashboardContainer
. This element will be used in therenderDashboard()
method to display the dashboard within it.const customHTML = ` <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1" /> </head> <body style="margin:0;padding:0;overflow:hidden;"> <div id="dashboardContainer" style="width:100%;height:100vh;"></div> </body> </html>`; const injectedJavaScript = ` (function() { function loadScript(url, callback) { var script = document.createElement('script'); script.src = url; script.onload = callback; script.onerror = function() { window.ReactNativeWebView.postMessage("Script loading failed."); }; document.head.appendChild(script); } function renderDashboard() { try { const dashboard = BoldBI.create({ serverUrl: "${ServerUrl + '/' + SiteIdentifier}", dashboardId: "${DashboardId}", embedContainerId: "dashboardContainer", authorizationServer: { url: "${apiHost+authorizationServerAPI}" } }); dashboard.loadDashboard(); } catch (error) { console.error("Error loading dashboard:", error); } } loadScript('https://cdn.boldbi.com/embedded-sdk/v11.2.7/boldbi-embed.js', renderDashboard); })(); true; `; return ( <WebView source={{ html: customHTML }} mixedContentMode="always" injectedJavaScript={injectedJavaScript} javaScriptEnabled={true} originWhitelist={["*"]} onMessage={(event) => console.log("WebView message:", event.nativeEvent.data)} /> ); }
-
After that, add a virtual device and run the Metro bundler in the terminal using the command
npx react-native start
. -
Finally, run the sample in the Android emulator using the command
npx react-native run-android
.