Skip to content

Add Angular example #35

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 28, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ci/prepare_playwright.sh
Original file line number Diff line number Diff line change
@@ -9,3 +9,4 @@ set -eux
./single_example.sh typescript vanilla_vite
./single_example.sh typescript react_vite
./single_example.sh typescript vue_vite
./single_example.sh typescript angular_ng
9 changes: 8 additions & 1 deletion ci/single_example.sh
Original file line number Diff line number Diff line change
@@ -12,9 +12,16 @@ fi
export TYPE=$1
export EXAMPLE=$2

export SANITISED_EXAMPLE=$EXAMPLE

if [[ $EXAMPLE =~ _vite$ ]]; then
export PORT=5173
export SERVE_CMD="npm run dev"
elif [[ $EXAMPLE =~ ^angular_ng$ ]]; then
export PORT=4200
export SERVE_CMD="npm run start"
# Angular annoyingly converts underscores to dashes
export SANITISED_EXAMPLE=angular-ng
else
export PORT=4500
export SERVE_CMD="npm run serve"
@@ -74,7 +81,7 @@ EOF
cat > temp.json << EOF
{
"scripts": {
"serve": "npm explore $EXAMPLE -- $SERVE_CMD",
"serve": "npm explore $SANITISED_EXAMPLE -- $SERVE_CMD",
"test": "playwright test",
"test:ui": "playwright test --ui"
}
138 changes: 138 additions & 0 deletions ci/typescript/create_angular_ng.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
#!/usr/bin/env bash

set -eux

export OUTPUT_DIRECTORY=../temp/typescript/angular_ng

mkdir -p $OUTPUT_DIRECTORY
cd $OUTPUT_DIRECTORY
rm -rf *

function merge-json() {
# merge the second json file into the first.
TEMP_FILE=$(mktemp)
jq '. * input' $1 $2 > TEMP_FILE && mv TEMP_FILE $1
}

# 1. Install @angular/cli
npm install -g @angular/cli

# 2. Create Angular application
ng new angular_ng --directory ./ --minimal --routing=false --skip-git --ssr=false --style=css

# 3. Build and serve the initial project
# npm run build
# # npm run start
# In a web browser navigate to http://localhost:4200/

# 4. Add BokehJS dependency to this project. This assumes the package has been built and copied to the root directory of this repository as outlined in the top-level README.md.
npm install ../../../../bokeh-bokehjs-3.8.0-dev.1.tgz

# 5. Create a new file src/app/bokeh-js/bokeh-js.component.ts containing a BokehJS plot component
mkdir -p src/app/bokeh-js
cat > src/app/bokeh-js/bokeh-js.component.ts << EOF
import { Component, OnInit } from '@angular/core'
import * as Bokeh from "@bokeh/bokehjs";

function create_bokehjs_plot(): Bokeh.Column {
const source = new Bokeh.ColumnDataSource({data: { x: [0.1, 0.9], y: [0.1, 0.9], size: [40, 10] }});

const plot = Bokeh.Plotting.figure({
title: "Example BokehJS plot", height: 500, width: 500,
x_range: [0, 1], y_range: [0, 1], sizing_mode: "stretch_width",
});

plot.scatter({ field: "x" }, { field: "y" }, {source, size: { field: "size" }});

const button = new Bokeh.Widgets.Button({label: "Click me to add a point", button_type: "primary"});
function button_callback() {
const data = source.data as any;
data.x.push(Math.random());
data.y.push(Math.random());
data.size.push(10 + Math.random()*30);
source.change.emit();
}
button.on_click(button_callback);

return new Bokeh.Column({children: [plot, button], sizing_mode: "stretch_width"});
}

@Component({
selector: 'app-bokeh-js',
imports: [],
template: \`<div id="target"></div>\`,
styles: \`\`
})

export class BokehJSComponent implements OnInit {
ngOnInit() {
console.info("BokehJS version:", Bokeh.version);
Bokeh.Plotting.show(create_bokehjs_plot(), "#target");
}
}
EOF

# 6. Replace src/app/app.component.ts so that it uses the BokehJSComponent
cat > src/app/app.component.ts << EOF
import { Component } from '@angular/core'
import { BokehJSComponent } from './bokeh-js/bokeh-js.component';

@Component({
selector: 'app-root',
imports: [BokehJSComponent],
template: \`<app-bokeh-js></app-bokeh-js>\`,
styles: [],
})

export class AppComponent {}
EOF

# 7. Remove some build warnings by allowing non ESM imports by adding to angular.json
cat > temp.json << EOF
{
"projects": {
"angular_ng": {
"architect": {
"build": {
"options": {
"allowedCommonJsDependencies": [
"@bokeh/bokehjs",
"mathjax-full",
"regl"
]
}
}
}
}
}
}
EOF
merge-json angular.json temp.json
rm temp.json

# 8. Remove bundle size limits in angular.json by setting the "budgets" to an empty array
cat > temp.json << EOF
{
"projects": {
"angular_ng": {
"architect": {
"build": {
"configurations": {
"production": {
"budgets": [
]
}
}
}
}
}
}
}
EOF
merge-json angular.json temp.json
rm temp.json

# 9. Rebuild and Serve the project
npm run build
# npm run start
# In a web browser navigate to http://localhost:4200/
120 changes: 120 additions & 0 deletions recipes/src/recipes/typescript/angular_ng_recipe.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { Recipe } from '../../recipe';
import { CommandStep, CreateFileStep, MergeJsonStep, ReplaceFileStep } from '../../step';
import { baseTypeScriptExample } from './common';

export class AngularNgRecipe extends Recipe {
constructor() {
super(
'typescript',
'angular',
'ng',
'The Angular web framework includes its own builder `ng` in the `@angular/cli` package'
);

this.add(new CommandStep(
'Install `@angular/cli`',
['npm install -g @angular/cli']
));

this.add(new CommandStep(
'Create Angular application',
['ng new angular_ng --directory ./ --minimal --routing=false --skip-git --ssr=false --style=css']
));

this.add(new CommandStep(
'Build and serve the initial project',
['npm run build', 'npm run start'],
'In a web browser navigate to http://localhost:4200/',
true
));

this.add(new CommandStep(
'Add BokehJS dependency to this project. This assumes the package has been built and ' +
'copied to the root directory of this repository as outlined in the top-level `README.md`.',
['npm install ../../../../bokeh-bokehjs-3.8.0-dev.1.tgz']
));

this.add(new CreateFileStep(
'Create a new file `src/app/bokeh-js/bokeh-js.component.ts` containing a BokehJS plot component',
'src/app/bokeh-js/bokeh-js.component.ts',
"import { Component, OnInit } from '@angular/core'\n" +
baseTypeScriptExample.import + "\n" +
baseTypeScriptExample.function + "\n" +
"@Component({\n" +
" selector: 'app-bokeh-js',\n" +
" imports: [],\n" +
' template: \\`<div id="target"></div>\\`,\n' +
" styles: \\`\\`\n" +
"})\n\n" +
"export class BokehJSComponent implements OnInit {\n" +
" ngOnInit() {\n" +
" " + baseTypeScriptExample.version +
" " + baseTypeScriptExample.show() +
" }\n" +
"}")
);

this.add(new ReplaceFileStep(
'Replace `src/app/app.component.ts` so that it uses the `BokehJSComponent`',
'src/app/app.component.ts',
"import { Component } from '@angular/core'\n" +
"import { BokehJSComponent } from './bokeh-js/bokeh-js.component';\n\n" +
"@Component({\n" +
" selector: 'app-root',\n" +
" imports: [BokehJSComponent],\n" +
" template: \\`<app-bokeh-js></app-bokeh-js>\\`,\n" +
" styles: [],\n" +
"})\n\n" +
"export class AppComponent {}")
);

this.add(new MergeJsonStep(
'Remove some build warnings by allowing non ESM imports by adding to `angular.json`',
'angular.json',
`{
"projects": {
"angular_ng": {
"architect": {
"build": {
"options": {
"allowedCommonJsDependencies": [
"@bokeh/bokehjs",
"mathjax-full",
"regl"
]
}
}
}
}
}
}`)
);

this.add(new MergeJsonStep(
'Remove bundle size limits in `angular.json` by setting the `"budgets"` to an empty array',
'angular.json',
`{
"projects": {
"angular_ng": {
"architect": {
"build": {
"configurations": {
"production": {
"budgets": [
]
}
}
}
}
}
}
}`)
);

this.add(new CommandStep(
'Rebuild and Serve the project',
['npm run build', 'npm run start'],
'In a web browser navigate to http://localhost:4200/'
));
}
}
1 change: 1 addition & 0 deletions recipes/src/recipes/typescript/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './angular_ng_recipe';
export * from './react_vite_recipe';
export * from './vanilla_rspack_recipe';
export * from './vanilla_vite_recipe';
1 change: 0 additions & 1 deletion recipes/src/recipes/typescript/react_vite_recipe.ts
Original file line number Diff line number Diff line change
@@ -42,7 +42,6 @@ export class ReactViteRecipe extends Recipe {
export default App`)
);


this.add(new ReplaceFileStep(
'Remove CSS lines from `src/main.tsx` by replacing it',
'src/main.tsx',
2 changes: 1 addition & 1 deletion recipes/src/step.ts
Original file line number Diff line number Diff line change
@@ -43,7 +43,7 @@ export class CommandStep extends Step {
const allPrefix = this.ignoreIfBash ? '# ' : '';
for (const command of this.commands) {
let prefix = allPrefix;
if (command === 'npm run serve' || command === 'npm run dev') {
if (command === 'npm run serve' || command === 'npm run dev' || command === 'npm run start') {
prefix = '# ' + prefix;
}
fs.writeSync(fd, prefix + command + '\n');
142 changes: 142 additions & 0 deletions typescript/angular_ng/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
# Angular ng typescript example

The Angular web framework includes its own builder `ng` in the `@angular/cli` package

1. Install `@angular/cli`

```bash
npm install -g @angular/cli
```

2. Create Angular application

```bash
ng new angular_ng --directory ./ --minimal --routing=false --skip-git --ssr=false --style=css
```

3. Build and serve the initial project

```bash
npm run build
npm run start
```

In a web browser navigate to http://localhost:4200/

4. Add BokehJS dependency to this project. This assumes the package has been built and copied to the root directory of this repository as outlined in the top-level `README.md`.

```bash
npm install ../../../../bokeh-bokehjs-3.8.0-dev.1.tgz
```

5. Create a new file `src/app/bokeh-js/bokeh-js.component.ts` containing a BokehJS plot component containing

```ts
import { Component, OnInit } from '@angular/core'
import * as Bokeh from "@bokeh/bokehjs";
function create_bokehjs_plot(): Bokeh.Column {
const source = new Bokeh.ColumnDataSource({data: { x: [0.1, 0.9], y: [0.1, 0.9], size: [40, 10] }});
const plot = Bokeh.Plotting.figure({
title: "Example BokehJS plot", height: 500, width: 500,
x_range: [0, 1], y_range: [0, 1], sizing_mode: "stretch_width",
});
plot.scatter({ field: "x" }, { field: "y" }, {source, size: { field: "size" }});
const button = new Bokeh.Widgets.Button({label: "Click me to add a point", button_type: "primary"});
function button_callback() {
const data = source.data as any;
data.x.push(Math.random());
data.y.push(Math.random());
data.size.push(10 + Math.random()*30);
source.change.emit();
}
button.on_click(button_callback);
return new Bokeh.Column({children: [plot, button], sizing_mode: "stretch_width"});
}
@Component({
selector: 'app-bokeh-js',
imports: [],
template: `<div id="target"></div>`,
styles: ``
})
export class BokehJSComponent implements OnInit {
ngOnInit() {
console.info("BokehJS version:", Bokeh.version);
Bokeh.Plotting.show(create_bokehjs_plot(), "#target");
}
}
```
6. Replace `src/app/app.component.ts` so that it uses the `BokehJSComponent` containing
```ts
import { Component } from '@angular/core'
import { BokehJSComponent } from './bokeh-js/bokeh-js.component';
@Component({
selector: 'app-root',
imports: [BokehJSComponent],
template: `<app-bokeh-js></app-bokeh-js>`,
styles: [],
})
export class AppComponent {}
```
7. Remove some build warnings by allowing non ESM imports by adding to `angular.json`
```.json
{
"projects": {
"angular_ng": {
"architect": {
"build": {
"options": {
"allowedCommonJsDependencies": [
"@bokeh/bokehjs",
"mathjax-full",
"regl"
]
}
}
}
}
}
}
```
8. Remove bundle size limits in `angular.json` by setting the `"budgets"` to an empty array
```.json
{
"projects": {
"angular_ng": {
"architect": {
"build": {
"configurations": {
"production": {
"budgets": [
]
}
}
}
}
}
}
}
```
9. Rebuild and Serve the project
```bash
npm run build
npm run start
```
In a web browser navigate to http://localhost:4200/