Hello everyone,
I am trying to use BokehJS inside an angular app, and I am failing miserably. Please note that I am not familiar at all with Angular and front-end technologies in general, so I’m probably in way over my head. Any help would be greatly appreciated.
I have written a Python script that generates a JSON plot with
bokeh.embed.json_item
. I am now attempting to use BokehJS to display the plot where I want it to appear in the angular app.
To do so I have installed
this node package
.
Then I have added the following line to the
.ts
file of my Angular component :
import embed from "@bokeh/bokehjs";
But this prevents the application from compiling, with the following errors :
ERROR in node_modules/@bokeh/bokehjs/build/js/types/core/properties.d.ts(2,13): error TS1005: '=' expected.
node_modules/@bokeh/bokehjs/build/js/types/core/properties.d.ts(2,31): error TS1005: ';' expected.
node_modules/@bokeh/bokehjs/build/js/types/core/view.d.ts(1,13): error TS1005: '=' expected.
node_modules/@bokeh/bokehjs/build/js/types/core/view.d.ts(1,31): error TS1005: ';' expected.
node_modules/@bokeh/bokehjs/build/js/types/index.d.ts(3,10): error TS1005: 'from' expected.
node_modules/@bokeh/bokehjs/build/js/types/index.d.ts(3,13): error TS1005: ';' expected.
node_modules/@bokeh/bokehjs/build/js/types/index.d.ts(3,19): error TS1005: ';' expected.
node_modules/@bokeh/bokehjs/build/js/types/index.d.ts(3,24): error TS1005: ';' expected.
node_modules/@bokeh/bokehjs/build/js/types/index.d.ts(4,10): error TS1005: 'from' expected.
node_modules/@bokeh/bokehjs/build/js/types/index.d.ts(4,13): error TS1005: ';' expected.
node_modules/@bokeh/bokehjs/build/js/types/index.d.ts(4,22): error TS1005: ';' expected.
node_modules/@bokeh/bokehjs/build/js/types/index.d.ts(4,27): error TS1005: ';' expected.
node_modules/@bokeh/bokehjs/build/js/types/index.d.ts(5,10): error TS1005: 'from' expected.
node_modules/@bokeh/bokehjs/build/js/types/index.d.ts(5,13): error TS1005: ';' expected.
node_modules/@bokeh/bokehjs/build/js/types/index.d.ts(5,22): error TS1005: ';' expected.
node_modules/@bokeh/bokehjs/build/js/types/index.d.ts(5,27): error TS1005: ';' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/ranges/data_range1d.d.ts(6,13): error TS1005: '=' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/ranges/data_range1d.d.ts(6,27): error TS1005: ';' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/button_tool.d.ts(6,13): error TS1005: '=' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/button_tool.d.ts(6,38): error TS1005: ';' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/tool.d.ts(10,13): error TS1005: '=' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/tool.d.ts(10,30): error TS1005: ';' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/tool.d.ts(11,13): error TS1005: '=' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/tool.d.ts(11,35): error TS1005: ';' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/tool.d.ts(12,13): error TS1005: '=' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/tool.d.ts(12,36): error TS1005: ';' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/tool.d.ts(13,13): error TS1005: '=' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/tool.d.ts(13,33): error TS1005: ';' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/tool.d.ts(14,13): error TS1005: '=' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/tool.d.ts(14,34): error TS1005: ';' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/tool.d.ts(15,13): error TS1005: '=' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/tool.d.ts(15,30): error TS1005: ';' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/tool.d.ts(16,13): error TS1005: '=' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/tool.d.ts(16,36): error TS1005: ';' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/tool.d.ts(17,13): error TS1005: '=' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/tool.d.ts(17,36): error TS1005: ';' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/tool.d.ts(18,13): error TS1005: '=' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/tool.d.ts(18,37): error TS1005: ';' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/tool.d.ts(19,13): error TS1005: '=' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/tool.d.ts(19,38): error TS1005: ';' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/tool.d.ts(20,13): error TS1005: '=' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/tool.d.ts(20,34): error TS1005: ';' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/tool.d.ts(21,13): error TS1005: '=' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/tool.d.ts(21,32): error TS1005: ';' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/tool.d.ts(22,13): error TS1005: '=' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/tool.d.ts(22,31): error TS1005: ';' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/tool.d.ts(23,13): error TS1005: '=' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/tool.d.ts(23,31): error TS1005: ';' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/tool.d.ts(24,13): error TS1005: '=' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/tool.d.ts(24,31): error TS1005: ';' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/tool.d.ts(25,13): error TS1005: '=' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/tool.d.ts(25,32): error TS1005: ';' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/tool.d.ts(26,13): error TS1005: '=' expected.
node_modules/@bokeh/bokehjs/build/js/types/models/tools/tool.d.ts(26,31): error TS1005: ';' expected.
Could you please give me a few pointers to help me understand where I took a wrong turn ?
No idea ? If I can provide extra information, please tell me.
I have updated nodejs and npm to latest versions, but it did not help.
Thanks in advance
@JYannick
I suspect that the radio silence is that you’re working on a less common integration problem than the typical user.
I don’t personally have any experience with Angular so I cannot help with the topic directly, but in the interest of starting the discussion, I’ll ask whether Angular is a requirement for your specific application or it chosen because it seemed like a reasonable starting point.
If Angular is not a requirement, there are a number of examples embedding Bokeh in other servers like Flask, for example. https://github.com/bokeh/bokeh/tree/2.0.2/examples/
Thank you @_jm !
I understand that my problem is very specific, and that most users here use Bokeh directly from Python. This is also usually my case, I have a more pythonic background so I was hoping some users of BokehJS might help me understand the issue when importing the library.
Unfortunately Angular is a requirement here. I am attempting to embed Bokeh plots into an existing Angular application, that is far too big to be rewritten using another technology. After some research I could not find anything as powerful as Bokeh in the JavaScript ecosystem, and since Bokeh provided many embedding features I decided to attempt an integration. Unfortunately, it seems more complicated than it looked like at first glance.
I think I have a solution ! Well, I have another problem afterwards, but at least now I can import BokehJS into my angular app.
Turns out my application was using an old version of Angular. I created a new prototype from scratch, using the latest version Angular 10, and this prototype can import Bokeh just fine with the following statement in a .ts component file : import * as Bokeh from "@bokeh/bokehjs"
However, when I’m attempting to actually make use of the library, I encounter the following issue :
My code snippet :
var item = JSON.parse('[...a JSON string exported from python via bokeh.embed.json_item()...]');
Bokeh.embed.embed_item(item, "bokeh-plot");
And the error message:
Failed to compile.
./node_modules/@bokeh/bokehjs/build/js/lib/index.js 3:9
Module parse failed: Unexpected token (3:9)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| export { version } from "./version";
| export { index } from "./embed";
> export * as embed from "./embed";
| export * as protocol from "./protocol";
| export * as _testing from "./testing";
I have found a reference to this issue here (the first method described in the opening post). However I do not understand the proposed solution, and how to implement it with Angular. It seems that Babel is not an issue with Angular, according to this: angular5 - Is Babel being used as compiler (AOT or JIT) in angular 5 - Stack Overflow
I see that @mateusz was very helpful in this other topic: if you could give me a few pointers regarding this issue with angular, it would help me tremendously.
If it can help, here is a complete procedure to reproduce my issue from scratch:
install nodejs : Node.js
install angular-cli : npm install -g @angular/cli
initialize a new angular project in the current directory : ng new angular10BokehJSexample
enter the new project directory : cd angular10BokehJSexample
(optional) check that the example angular app works : npm start
and open your browser on URL http://localhost:4200
install BokehJS : npm install @bokeh/bokehjs
open your favorite text editor and change the file src/app/app.module.ts
. Add the following line with the other imports at the top : import * as Bokeh from '@bokeh/bokehjs'
if you start the server at this stage, it should still work fine, meaning that BokehJS can be imported successfully (that was not the case with an old version of Angular)
still in the file src/app/app.module.ts
, change the class decalaration at the end of the file to make it look like this :
export class AppModule {
private testBokeh(){
var item = JSON.parse("just a test");
Bokeh.embed.embed_item(item);
(note: this is just a stub, the code does not work. I’ve put together a more complex code that is supposed to work, but this is sufficient to reproduce my issue)
run npm start
again, it cannot compile :
ERROR in ./node_modules/@bokeh/bokehjs/build/js/lib/index.js 3:9
Module parse failed: Unexpected token (3:9)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| export { version } from "./version";
| export { index } from "./embed";
> export * as embed from "./embed";
| export * as protocol from "./protocol";
| export * as _testing from "./testing";
Okay, I did not give up, and finally got this to work. If anyone else is interested, here is what I did. The main trick was to import just the required file from the build
subdirectory.
In the Python script
import json
from bokeh.embed import json_item
from bokeh.plotting import figure, output_file
p = figure()
p.circle([1], [1])
with(open("simple_plot.json", 'w')) as f:
f.write(json.dumps(json_item(p)))
print("done")
In my angular component
In the TypeScript file :
import * as Bokeh from '@bokeh/bokehjs/build/js/lib/embed';
let bokehJson = ....retrieve the JSON file content generated by Python...
Bokeh.embed_item(JSON.parse(bokehJson), "bokeh-div-id");
In the HTML template file:
<div id="bokeh-div-id"></div>
This should be sufficient for most uses. However I wanted to use a more complex Bokeh plot with widgets and tables: those must be imported manually, and only once to prevent multiple declarations warnings. So:
In the angular application file main.ts
import * as Widgets from '@bokeh/bokehjs/build/js/lib/models/widgets/index';
import * as Tables from '@bokeh/bokehjs/build/js/lib/models/widgets/tables/index';
import { register_models } from "@bokeh/bokehjs/build/js/lib/base";
register_models(Widgets);
register_models(Tables);
And with this, you should be good to go !