Using SpotFire JavaScript API with React Js
This is my first blog. First blog of my 27 year lifetime, I always wanted to write technical blogs and I wonder what stopped me, rather what made me start now. Let me tell you something about me to start off, I am a Software Developer and I am in love with JavaScript. I have been working on the Modern development frameworks on SharePoint(read SharePoint Framework) and that's when my tirade with the modern web stack started. I am not a guru or anything of that sort, but I have struggled, I think enough to help someone else not go through that. And that is why I think I am starting this.
So lets get right into it, this article is about rendering a SpotFire report(from TIBCO) into a web application(created with React JS), my major beef with most articles is that it is seldom end to end, a series of steps to get a final output in my local system. I agree its not possible for all topics and it increases the length, but I would like to do exactly that. Give you a series of steps starting from zero without missing any step to build the final application we intend to make.
And to help that cause let me give you the final result of what we are trying to achieve -
So lets start off, if you are reading this I will assume that you are either trying to specifically render a SpotFire report into a React Application, or you are in general working with React and doing some sort of data visualisation, that's what I was doing.
React is a js framework developed by Facebook, and I wont go into the details of how React works and when or why should you use it. I am taking a leap of faith that you love React as much as i do and you have chosen to work with it. But I would create a react application from ground up so that you can follow along.
I am using an npm package called create-react-app, its the best tool in my opinion to get started with a React application. It basically creates your project structure, includes web pack and Babel, configures them for you, provides a lot of goodness like live reload, hosts it on your localhost, basically you write your code and then run it with npm start, and thats it, your code will be bundled and run in the browser with full ES6 support.
I work on a windows system and so i like using a console emulator called cmder, check it out if you don't already use it, its a nice upgrade on windows command prompt.
Now lets get started, open your preferred console emulator and then go to a project directory where you would create the application.
Creating a shiny new React Application
To use create-react-app you need to install it globally, make sure you have the latest stable node and npm installed in the system. Then run the following commands -
npm install -g create-react-app
And then create a new project directory, I am calling it spotfire-react :
create-react-app spotfire-react
This would create a new folder with all files required to launch a new React application, cd into the newly created folder - "spotfire-react" in this case, and then open this folder with your preferred code editor, I use Visual studio code, you are free to use anything you want. If you are using visual studio code, you can open the current directory directly with the command - "code .", provided your PATH variable has VS Code executable pointed at.
Take a look at the folder structure -
Lets go through the project structure, there is the node_modules folder which has all the node packages installed like react, react-dom and other packages.
We have the public folder which has the index.html file which is the html file where your react application is hosted, you have some boilerplate code written there, the most important part is that it has a div called root, where your react application is going to be hosted.
Lets talk about the meat of the application, the src folder, where the source code will be kept, index.js is the entry point of the app, and the most important thing it does is that it renders the react component and in this case its the App component in the App.js file.
You can immidiately run this by running the command npm run start -
Now that we have our react application up and running lets jump into SpotFire Javascript API and its integration into our application in the next step.
Recommended by LinkedIn
Calling the SpotFire Javascript API from the React Application
SpotFire reports require a server where spotfire needs to be installed and configured, for those who have not worked with SpotFire, spotfire is from TIBCO, and its a data visualization tool at its core. You can create pretty complex reports using SpotFire. Now if SpotFire reports are to be rendered in a custom web application, you need to hook into its JavaScript API, and then create an application with JS code.
The first step in this is to include a script tag in your code, to load the actual spotfire api -
<script type="text/javascript" src="https://spotfire.cloud.tibco.com/spotfire/wp/GetJavaScriptApi.ashx?Version=7.5"></script>
I am using a public spotfire cloud server for now to demonstrate this, and you can get more details on spotfire js api at - Spotfire JS API
Add the above script somewhere in the head section of your index.html page in the public folder.
Now lets start updating our react component, App.js, I could have created a new component, but its ok, I will add an extra div in the render method to add the spotfire report.
Basically Spotfire JS API, adds a new iframe inside the div that you pass to the spotfire webplayer application, and opens the report inside the iframe, you need to add a div as a placeholder where the iframe is going to be rendered.
My main code to create the spotfire webplayer is written in componentDidMount lifecycle hook of react, to call into the spotfire api and render the report.
componentDidMount() {
//write logic to render the spotfire widget into the div element created inside render methodlet customizationFromProp = this.props.customization;
let customizationSFObject = new spotfire.webPlayer.Customization();
customizationSFObject.showStatusBar = false;
customizationSFObject.showToolBar = false;
customizationSFObject.showPageNavigation = false;
var spotFireApp = new spotfire.webPlayer.Application("https://spotfire.cloud.tibco.com/spotfire/wp/", customizationSFObject, "/Gallery/Expense Analyzer Dashboard");
var doc = spotFireApp.openDocument("container");
spotFireApp.onError(this.errorCallBack);
}
Updated render method looks like this -
render() {
return (
<div className="App"><div className="App-header"><img src={logo} className="App-logo" alt="logo" /><h2>Welcome to React</h2></div><p className="App-intro">
To get started, edit <code>src/App.js</code> and save to reload.
</p><div><div id="container" style={{height:"600",width:"1200", marginLeft:150}}></div><div id="spotFireWidgetPlaceholder">
{this.state.errorState == true ? <div style={{color:"red",fontWeight:800}}>Error - {this.state.errorDesc}</div> : ""}
</div></div></div>
);
}
Complete App.js File -
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class App extends Component {
constructor(props) {
super(props);
this.state = {
errorState : false,
errorDesc : ""
}
this.errorCallBack = this.errorCallBack.bind(this);
}
errorCallBack(errorCode, description) {
//alert("An error occurred while processing the request. Error code: " + errorCode + "; Error description: " + description);this.setState({
errorState : true,
errorDesc : description
});
}
componentDidMount() {
//write logic to render the spotfire widget into the div element created inside render methodlet customizationFromProp = this.props.customization;
let customizationSFObject = new spotfire.webPlayer.Customization();
customizationSFObject.showStatusBar = false;
customizationSFObject.showToolBar = false;
customizationSFObject.showPageNavigation = false;
var spotFireApp = new spotfire.webPlayer.Application("https://spotfire.cloud.tibco.com/spotfire/wp/", customizationSFObject, "/Gallery/Expense Analyzer Dashboard");
var doc = spotFireApp.openDocument("container");
spotFireApp.onError(this.errorCallBack);
}
render() {
return (
<div className="App"><div className="App-header"><img src={logo} className="App-logo" alt="logo" /><h2>Welcome to React</h2></div><p className="App-intro">
To get started, edit <code>src/App.js</code> and save to reload.
</p><div><div id="container" style={{height:"600",width:"1200", marginLeft:150}}></div><div id="spotFireWidgetPlaceholder">
{this.state.errorState == true ? <div style={{color:"red",fontWeight:800}}>Error - {this.state.errorDesc}</div> : ""}
</div></div></div>
);
}
}
export default App;
Now if you have your browser open you will get the following error -
Failed to compile
./src/App.js
Line 26: 'spotfire' is not defined no-undef
Line 30: 'spotfire' is not defined no-undef
Search for the keywords to learn more about each error.
This error occurred during the build time and cannot be dismissed.
If you open the chrome debugging tools you will see that the spotfire object is correctly loaded, but the eslint here complains that spotfire is not defined, I would like to include spotfire as a global dependency and for that I would need to update my .eslintrc file.
create-react-app does not allow us to directly edit the .eslintrc file and use that, you would first need to run npm run eject, note that this is a irreversible step, this might lead to you breaking your existing react app, please proceed with caution in this step. This step basically brings all the configuration file used by create-react-app locally.
Now add a new file .eslintrc(note the dot at the start), and add the following code -
(If you have figured out a better way of doing this, by all means please share it with me)
{
"env": {
"browser": true,
"node": true,
"jasmine": true
},
"globals": {
"spotfire": true
},
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module",
"ecmaFeatures": {
"jsx": true,
"modules": true,
"experimentalObjectRestSpread": true
}
}
}
I have some other configurations going on, which you wont require in this case, the only important thing is to define spotfire as a global variable.
And that's it, if you have your browser running, then you should see the publicly available spotfire widget inside your app.
As I have mentioned this is my first blog, I am a newbie and would appreciate feedback, that's the only ask I have of you, any feedback technical as well as non technical is greatly appreciated.
Can you share the github repo?
Can you share the git repository? Could be easier to understand it better :)
Nice and helpful 👍.... Just wanted to add alternatively adding comment // eslint-disable-next-line before new spotfire.webplayer worked if not wanting to edit .eslintrc file
Hi Arnab, Even after adding .eslintrc file, it still showing the same error.Please let me know if there is better way to resolve the issue.
Very nice article Arnab...